Spaces:
Sleeping
Sleeping
import os | |
import time | |
import json | |
import openai | |
import gradio as gr | |
from datetime import datetime | |
from openai.error import RateLimitError, APIConnectionError, Timeout, APIError, \ | |
ServiceUnavailableError | |
from huggingface_hub import hf_hub_download, HfApi | |
def get_main_data(): | |
""" | |
Initializes the key for the api and returns the parameters for the scores, name of the possible authors | |
and prompts (the one for the conversation and another for the summary) | |
""" | |
openai.api_key = os.environ.get('API_KEY') | |
scores_parameters = [ | |
'Personalidad', 'Intereses', 'Lenguaje/Estilo', 'Autenticidad', 'Habilidad de conversaci贸n', | |
'Marca/Producto', 'Identificaci贸n', 'Experiencia de uso', 'Recomendacion', 'Conversaci贸n organica' | |
] | |
authors = ['Sofia', 'Eliza', 'Sindy', 'Carlos', 'Andres', 'Adriana', 'Carolina', 'Valeria'] | |
with open('prompt_conversation.txt', encoding='utf-8') as file: | |
prompt_conversation = file.read() | |
return scores_parameters, authors, prompt_conversation | |
def innit_bot(prompt: str): | |
""" | |
Initialize the bot by adding the prompt from the txt file to the messages history | |
""" | |
prompt.replace('HISTORY', '') | |
message_history = [{"role": "system", "content": prompt}] | |
return message_history | |
def make_visible(): | |
""" | |
Makes visible the returned elements | |
""" | |
return ( | |
gr.Chatbot.update(visible=True), | |
gr.Textbox.update(visible=True), | |
gr.Row.update(visible=True)) | |
def make_noninteractive(): | |
""" | |
Makes no interactive the returned elements | |
""" | |
return gr.Dropdown.update(interactive=False) | |
def call_api(msg_history: gr.State, cost: gr.State): | |
""" | |
Returns the API's response | |
""" | |
response = openai.ChatCompletion.create( | |
model="gpt-4", | |
messages=msg_history, | |
temperature=0.8 | |
) | |
print("*" * 20) | |
print(msg_history) | |
print("*" * 20) | |
tokens_input = response['usage']['prompt_tokens'] | |
tokens_output = response['usage']['completion_tokens'] | |
cost.append({'Model': 'gpt-4', 'Input': tokens_input, 'Output': tokens_output}) | |
return response | |
def handle_call(msg_history: gr.State, cost: gr.State): | |
""" | |
Returns the response and waiting time of the AI. It also handles the possible errors | |
""" | |
tries = 0 | |
max_tries = 3 | |
while True: | |
try: | |
start_time = time.time() | |
response = call_api(msg_history, cost) | |
end_time = time.time() | |
break | |
except (RateLimitError, APIError, Timeout, APIConnectionError, ServiceUnavailableError) as e: | |
print(e) | |
if tries == max_tries: | |
response = "Despues de muchos intentos, no se pudo completar la comunicacion con OpenAI. " \ | |
"Envia lo que tengas hasta el momento e inicia un chat nuevo dentro de unos minutos." | |
raise gr.Error(response) | |
tries += 1 | |
time.sleep(60) | |
needed_time = end_time - start_time | |
return response, needed_time | |
def get_template(chatbot_history: gr.Chatbot, previous_summary: gr.State): | |
with open('prompt_summary.txt', encoding='utf-8') as file: | |
template_summary = file.read() | |
conversation = '' | |
for i, msg in enumerate(chatbot_history): | |
conversation += f'Usuario: {msg[0]} \n' | |
conversation += f'Roomie: {msg[1]} \n' | |
template_summary = template_summary.replace('CONVERSATION', conversation) | |
return template_summary | |
def get_summary(chatbot_history: gr.Chatbot, previous_summary: gr.State, cost: gr.State): | |
msg = get_template(chatbot_history, previous_summary) | |
print(msg, end='\n\n') | |
with open('prompt_summary_system.txt', encoding='utf-8') as file: | |
system_prompt = file.read() | |
calling = [ | |
{"role": "system", "content": system_prompt}, | |
{"role": "user", "content": msg} | |
] | |
response = openai.ChatCompletion.create( | |
model="gpt-3.5-turbo", | |
messages=calling, | |
temperature=0 | |
) | |
tokens_input = response['usage']['prompt_tokens'] | |
tokens_output = response['usage']['completion_tokens'] | |
cost.append({'Model': 'gpt-3.5-turbo', 'Input': tokens_input, 'Output': tokens_output}) | |
return response["choices"][0]["message"]["content"] | |
def get_ai_answer( | |
msg: str, msg_history: gr.State, num_interactions: gr.State, previous_summary: gr.State, | |
cost: gr.State, chatbot_history: gr.Chatbot): | |
""" | |
Returns the response given by the model, all the message history so far and the seconds | |
the api took to retrieve such response. It also removes some messages in the message history | |
so only the last n (keep) are used (costs are cheaper) | |
""" | |
# Call GPT 3.5 | |
if num_interactions >= 2: | |
previous_output = msg_history.pop() | |
summary = get_summary(chatbot_history, previous_summary, cost) | |
with open('prompt_conversation.txt', encoding='utf-8') as file: | |
prompt_template = file.read() | |
prompt_template = prompt_template.replace('HISTORY', summary) | |
msg_history = [{"role": "system", "content": prompt_template}] | |
msg_history.append(previous_output) | |
print('RESUMEN DE GPT 3.5', summary, end='\n----------------------------------------------------------------\n') | |
else: | |
summary = '' | |
# Call GPT 4 | |
msg_history.append({"role": "user", "content": msg}) | |
response, needed_time = handle_call(msg_history, cost) | |
AI_response = response["choices"][0]["message"]["content"] | |
msg_history.append({'role': 'assistant', 'content': AI_response}) | |
return AI_response, msg_history, needed_time, summary | |
def get_answer( | |
msg: str, msg_history: gr.State, chatbot_history: gr.Chatbot, | |
waiting_time: gr.State, num_interactions: gr.State, previous_summary: gr.State, | |
cost: gr.State): | |
""" | |
Cleans msg box, adds the new message to the message history, | |
gets the answer from the bot and adds it to the chatbot history | |
and gets the time needed to get such answer and saves it | |
""" | |
# Get bot answer (output), messages history and waiting time | |
AI_response, msg_history, needed_time, summary = get_ai_answer( | |
msg, msg_history, num_interactions, previous_summary, cost, chatbot_history | |
) | |
# Save waiting time | |
waiting_time.append(needed_time) | |
# Save output in the chat | |
chatbot_history.append((msg, AI_response)) | |
num_interactions += 1 | |
return "", msg_history, chatbot_history, waiting_time, num_interactions, summary, cost | |
def save_scores( | |
author: gr.Dropdown, history: gr.Chatbot, waiting_time: gr.State, opinion: gr.Textbox, | |
cost: gr.State, *score_values): | |
""" | |
Saves the scores and chat's info into the json file | |
""" | |
# Get the parameters for each score | |
score_parameters, _, _ = get_main_data() | |
# Get the score of each parameter | |
scores = dict() | |
for parameter, score in zip(score_parameters, score_values): | |
# Check the score is a valid value if not, raise Error | |
if score is None: | |
raise gr.Error('Asegurese de haber seleccionado al menos 1 opcion en cada categoria') | |
scores[parameter] = score | |
# Get all the messages including their reaction | |
chat = [] | |
for conversation in history: | |
info = { | |
'message': conversation[0], | |
'answer': conversation[1], | |
'waiting': waiting_time.pop(0) | |
} | |
chat.append(info) | |
date = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
with open('prompt_conversation.txt', encoding='utf-8') as file: | |
prompt = file.read() | |
# Save the info | |
session = dict( | |
prompt=prompt, | |
temperature=0.8, | |
scores=scores, | |
opinion=opinion, | |
chat=chat, | |
cost=cost, | |
author=author, | |
model='gpt-4', | |
date=date | |
) | |
# Open the file, add the new info and save it | |
hf_hub_download( | |
repo_id=os.environ.get('DATA'), repo_type='dataset', filename="data.json", token=os.environ.get('HUB_TOKEN'), | |
local_dir="./" | |
) | |
with open('data.json', 'r') as infile: | |
past_sessions = json.load(infile) | |
# Add the new info | |
past_sessions['sessions'].append(session) | |
with open('data.json', 'w', encoding='utf-8') as outfile: | |
json.dump(past_sessions, outfile, indent=4, ensure_ascii=False) | |
# Save the updated file | |
api = HfApi(token=os.environ.get('HUB_TOKEN')) | |
api.upload_file( | |
path_or_fileobj="data.json", | |
path_in_repo="data.json", | |
repo_id=os.environ.get('DATA'), | |
repo_type='dataset' | |
) | |
# Return a confirmation message | |
return 'Done' | |