import os import openai from openai import OpenAI from dotenv import load_dotenv, find_dotenv import re import matplotlib.pyplot as plt sample_input = \ """ Visitor: Heyyy Visitor: How are you this evening Agent: better now ;) call me Visitor: I am at work for now, be off around 10pm Visitor: Need some company Visitor: Are you independent honey Agent: 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? Agent: we are with some guys who are trying to spread awareness of the realities of this "industry". Agent: https://exoduscry.com/choice/ Visitor: Thanks Agent: 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 Visitor: Ooohhh Agent: selling their body to make ends meet or appease a pimp Visitor: That's really awful Agent: 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? Visitor: Well iam just looking for attention Visitor: My marriage is not going well lol Agent: 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 Agent: hey, thanks for sharing that my man. i know it can be hard Agent: marraige is the most humbling of relationships, isnt it? Visitor: She leaves with her friends n no time for me Agent: ive been there my guy. i know that it is alot easier to numb that loneliness for sure Visitor: I want to be faithful Agent: does your wife know how you feel when she chooses her friends instead of you? Visitor: I been drinking lately Visitor: Yes, she takes pills Agent: if so, i hope you are praying for her to realize the hurt she is causing and to seek change Visitor: She had surgery 4 yes ago n it's been hard for her n her addiction on pills Visitor: Yes for now i am looking for a female friend to talk n see what can we do for each other Agent: that is hard my man. physical pain is a huge obstacle in life for sure so i hear you Visitor: Well chat later. thanks Agent: have you considered pursuing other men who can encourage you instead of looking for the easy way out? Agent: what is your name my friend? i will be praying for you by name if you wouldnt mind sharing it Agent: 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 """ sample_output = \ """ Visitor: Heyyy [Greeting] Visitor: How are you this evening [Greeting] Agent: better now ;) call me [Openness] Visitor: I am at work for now, be off around 10pm [Interest] Visitor: Need some company [Interest] Visitor: Are you independent honey [Interest] Agent: 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? [Informative] Agent: we are with some guys who are trying to spread awareness of the realities of this "industry". [Informative] Agent: https://exoduscry.com/choice/ [Informative] Visitor: Thanks [Acceptance] Agent: 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 [Informative] Visitor: Ooohhh [Interest] Agent: selling their body to make ends meet or appease a pimp [Informative] Visitor: That's really awful [Remorse] Agent: 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? [Accusatory] Visitor: Well iam just looking for attention [Anxious] Visitor: My marriage is not going well lol [Anxious] Agent: 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 [Informative] Agent: hey, thanks for sharing that my man. i know it can be hard [Acceptance] Agent: marraige is the most humbling of relationships, isnt it? [Openness] Visitor: She leaves with her friends n no time for me [Annoyed] Agent: ive been there my guy. i know that it is alot easier to numb that loneliness for sure [Acceptance] Visitor: I want to be faithful [Acceptance] Agent: does your wife know how you feel when she chooses her friends instead of you? [Curiosity] Visitor: I been drinking lately [Anxious] Visitor: Yes, she takes pills [Anxious] Agent: if so, i hope you are praying for her to realize the hurt she is causing and to seek change [Interest] Visitor: She had surgery 4 yes ago n it's been hard for her n her addiction on pills [Anxious] Visitor: Yes for now i am looking for a female friend to talk n see what can we do for each other [Informative] Agent: that is hard my man. physical pain is a huge obstacle in life for sure so i hear you [Acceptance] Visitor: Well chat later. thanks [Openness] Agent: have you considered pursuing other men who can encourage you instead of looking for the easy way out? [Informative] Agent: what is your name my friend? i will be praying for you by name if you wouldnt mind sharing it [Openness] Agent: 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 [Openness] Sentiment Flow Analysis on the Visitor's side: The Visitor begins the conversation with a friendly and casual tone, expressing a desire for company and showing interest in the Agent. \ 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 \ and a sense of confusion and remorse about the situation. The Visitor then reveals personal issues, indicating anxiety and seeking attention due to marital problems. \ The sentiment continues to be anxious as the Visitor discusses personal struggles with alcohol and his wife's pill addiction, \ showing a need for companionship and support. Despite the heavy topics, the Visitor expresses a desire to remain faithful and shows interest in finding a friend, albeit with a hint of desperation. \ The Visitor openly takes the Agent's information and the conversation flows smoothly as both the Visitor and the Agent \ show openness toward each other. """ def get_completion(conversation, model="gpt-4-1106-preview"): prompt = f""" The EPIK Project is about mobilizing male allies \ to disrupt the commercial sex market, \ equipping them to combat the roots of exploitation \ and encouraging them to collaborate effectively \ with the wider anti-trafficking movement. \ You are an adept expert conversation sentiment analyzer. \ Your job is to analyze the conversation and provide a report \ based on the sentiment flow of the conversation on the visitor's \ perspective. Visitor indicates the potential buyer, and Agent indicates the volunteer from EPIK. \ The conversation is going to be given in the format: Visitor: Agent: The actual conversation is delimited by triple backticks ```{conversation}``` Here is the list of sentiment labels you should use delimited by square brackets. \ ["Openness", "Anxious", "Confused", "Disapproval", "Remorse", "Accusatory", \ "Denial", "Obscene", "Uninterested", "Annoyed", "Informative", "Greeting", \ "Interest", "Curiosity", "Acceptance"] Your output should look like: ``` Speaker: [sentiment label] ... Speaker: [sentiment label] ``` where Speaker can either be Visitor or Agent. Then, you should write your report on the sentiment flow \ on the Visitor's side below. Here is a sample input delimited by triple backticks ```{sample_input}``` Here is a same output that you should try to aim for delimited by sqaure brackets [{sample_output}] """ client = OpenAI() messages = [{"role": "user", "content": prompt}] response = client.chat.completions.create( model=model, messages=messages, temperature=0, # this is the degree of randomness of the model's output ) analysis = response.choices[0].message.content def extract_conv_with_labels(analysis): analysis = analysis.replace("\n", " ") BETWEEN_BACKTICKS = "\\`\\`\\`(.*?)\\`\\`\\`" match = re.search(BETWEEN_BACKTICKS, analysis) if match: conv_with_labels = match.group()[4:-4] else: return "OUTPUT IS IN WRONG FORMAT" # just reformatting it for better format conv_with_labels = conv_with_labels.split('] ') temp = [utterance + ']' for utterance in conv_with_labels[:-1]] conv_with_labels = temp + [conv_with_labels[-1]] return conv_with_labels grouped_sentiments = { '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 sentiment_flow_plot(conv): conv_with_labels = extract_conv_with_labels(analysis) num_utterances = len(conv_with_labels) visitor_Y = [''] * num_utterances agent_Y = [''] * num_utterances for i in range(num_utterances): utterance = conv_with_labels[i] match = re.search(r'\[(.*?)\]$', utterance) if match: label = match.group(1) else: print("OUTPUT IS IN WRONG FORMAT") break if utterance.startswith('Visitor'): visitor_Y[i] = label if i == 0: agent_Y[i] = 'None' else: agent_Y[i] = agent_Y[i-1] elif utterance.startswith('Agent'): agent_Y[i] = label if i == 0: visitor_Y[i] = 'None' else: visitor_Y[i] = visitor_Y[i-1] X = range(1,num_utterances+1) visitor_Y_converted = [grouped_sentiments[visitor_Y[i]] for i in range(num_utterances)] agent_Y_converted = [grouped_sentiments[agent_Y[i]] for i in range(num_utterances)] plt.style.use('seaborn') fig, ax = plt.subplots() ax.plot(X, visitor_Y_converted, label='Visitor', color='blue', marker='o') ax.plot(X, agent_Y_converted, label='Agent', color='green', marker='o') plt.yticks(ticks=[-3,-2,-1,0,1,2,3], labels=['Disapproval/Accusatory/Denial/Obscene', 'Anxious/Confused/Annoyed/Remorse', 'Uninterested', 'Greeting/None', 'Informative', 'Interest/Curiosity', 'Acceptance/Openness']) for label in ax.get_yticklabels(): label.set_rotation(45) plt.xlabel('Number of utterances') plt.ylabel('Sentiments') plt.title('Sentiment Flow Plot') plt.close(fig) return fig fig = sentiment_flow_plot(analysis) return response.choices[0].message.content, fig def set_key(key): with open("_.env", "w") as file: file.write(f"OPENAI_API_KEY={key}") load_dotenv(find_dotenv("_.env"), override=True) return import gradio as gr with gr.Blocks() as gpt_analysis: gr.Markdown("## Conversation Analysis") gr.Markdown( "This is a custom GPT model designed to provide \ a report on overall sentiment flow of the conversation on the \ volunteer's perspective.
Click on them and submit them to the model to see how it works.") conversation = gr.Textbox(label="Input", lines=2) btn = gr.Button(value="Submit") api_key = gr.Textbox(label="Key", lines=1) btn_key = gr.Button(value="Submit Key") btn_key.click(set_key, inputs=api_key) with gr.Row(): output_box = gr.Textbox(value="", label="Output",lines=4) plot_box = gr.Plot(label="Analysis Plot") btn.click(get_completion, inputs=conversation, outputs=[output_box]) gr.TabbedInterface([gpt_analysis], ["GPT Analysis"]).launch(inline=False, debug=True)