Spaces:
Runtime error
Runtime error
add audio and video functionality
Browse files- app.py +32 -11
- backend_functions.py +480 -59
- gcp.py +28 -0
- utils.py +19 -0
app.py
CHANGED
@@ -3,7 +3,7 @@ import os
|
|
3 |
import time
|
4 |
|
5 |
from utils import make_invisible, make_visible
|
6 |
-
from backend_functions import
|
7 |
|
8 |
from dotenv import load_dotenv
|
9 |
load_dotenv()
|
@@ -11,21 +11,36 @@ load_dotenv()
|
|
11 |
|
12 |
|
13 |
with gr.Blocks() as main_app:
|
|
|
|
|
|
|
14 |
with gr.Tab('Chatbot'):
|
15 |
user_id = gr.State('') # id used to find the chat into the database
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
-
|
18 |
|
19 |
messages = gr.State([])
|
20 |
|
21 |
with gr.Row():
|
22 |
text = gr.Textbox(label='Write your question')
|
23 |
|
24 |
-
with gr.
|
25 |
-
with gr.
|
26 |
button_text = gr.Button(value='Submit text')
|
27 |
-
with gr.Column():
|
28 |
clear_button = gr.ClearButton([chat, messages])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
|
31 |
|
@@ -55,21 +70,27 @@ with gr.Blocks() as main_app:
|
|
55 |
# )
|
56 |
|
57 |
text.submit(
|
58 |
-
fn=
|
59 |
-
inputs=[text, chat, messages],
|
60 |
-
outputs=[chat]
|
61 |
).then(
|
62 |
lambda: None, None, [text]
|
63 |
)
|
64 |
|
65 |
button_text.click(
|
66 |
-
fn=
|
67 |
-
inputs=[text, chat, messages],
|
68 |
-
outputs=[chat]
|
69 |
).then(
|
70 |
lambda: None, None, [text]
|
71 |
)
|
72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
|
75 |
main_app.launch(debug=True, auth=(os.environ.get('SPACE_USERNAME'), os.environ.get('SPACE_PASSWORD')))
|
|
|
3 |
import time
|
4 |
|
5 |
from utils import make_invisible, make_visible
|
6 |
+
from backend_functions import get_answer, init_greeting, export_dataframe
|
7 |
|
8 |
from dotenv import load_dotenv
|
9 |
load_dotenv()
|
|
|
11 |
|
12 |
|
13 |
with gr.Blocks() as main_app:
|
14 |
+
|
15 |
+
times_functions = gr.State([[], [], []])
|
16 |
+
|
17 |
with gr.Tab('Chatbot'):
|
18 |
user_id = gr.State('') # id used to find the chat into the database
|
19 |
+
|
20 |
+
with gr.Column():
|
21 |
+
with gr.Row():
|
22 |
+
chat = gr.Chatbot(label="Chatbot Crunchyroll")
|
23 |
+
output_video = gr.Video(interactive=False, label='Video', autoplay=True, height=400)
|
24 |
|
25 |
+
output_audio = gr.Audio(interactive=False, label='Audio', autoplay=False)
|
26 |
|
27 |
messages = gr.State([])
|
28 |
|
29 |
with gr.Row():
|
30 |
text = gr.Textbox(label='Write your question')
|
31 |
|
32 |
+
with gr.Column():
|
33 |
+
with gr.Row():
|
34 |
button_text = gr.Button(value='Submit text')
|
|
|
35 |
clear_button = gr.ClearButton([chat, messages])
|
36 |
+
|
37 |
+
with gr.Tab('Times'):
|
38 |
+
|
39 |
+
columns = ["User Message", "Chatbot Response", "Standalone Question", "Create Embedding", "Query Pinecone",
|
40 |
+
"Context Prompt", "Final Response GPT", "Create Clean Message", "Create Audio Elevenlabs", "Create Video D-iD", "Final Time"]
|
41 |
+
table_times = gr.DataFrame(headers=columns, visible=False, interactive=False)
|
42 |
+
|
43 |
+
export_button = gr.Button(value="Export CSV")
|
44 |
|
45 |
|
46 |
|
|
|
70 |
# )
|
71 |
|
72 |
text.submit(
|
73 |
+
fn=get_answer,
|
74 |
+
inputs=[text, chat, messages, output_audio, output_video, table_times],
|
75 |
+
outputs=[chat, output_audio, output_video, table_times]
|
76 |
).then(
|
77 |
lambda: None, None, [text]
|
78 |
)
|
79 |
|
80 |
button_text.click(
|
81 |
+
fn=get_answer,
|
82 |
+
inputs=[text, chat, messages, output_audio, output_video, table_times],
|
83 |
+
outputs=[chat, output_audio, output_video, table_times]
|
84 |
).then(
|
85 |
lambda: None, None, [text]
|
86 |
)
|
87 |
|
88 |
+
export_button.click(
|
89 |
+
fn=export_dataframe,
|
90 |
+
inputs=table_times,
|
91 |
+
)
|
92 |
+
|
93 |
+
main_app.load(init_greeting, inputs=[chat, messages], outputs=[chat, messages])
|
94 |
|
95 |
|
96 |
main_app.launch(debug=True, auth=(os.environ.get('SPACE_USERNAME'), os.environ.get('SPACE_PASSWORD')))
|
backend_functions.py
CHANGED
@@ -1,12 +1,21 @@
|
|
1 |
import gradio as gr
|
2 |
-
import
|
3 |
import os
|
|
|
|
|
4 |
from openai import OpenAI
|
5 |
from pinecone import Pinecone
|
6 |
import uuid
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
from pymongo.mongo_client import MongoClient
|
|
|
8 |
from dotenv import load_dotenv
|
9 |
-
|
10 |
load_dotenv()
|
11 |
|
12 |
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
@@ -19,6 +28,15 @@ PINECONE_HOST = os.getenv("PINECONE_HOST")
|
|
19 |
DB_USER_NAME = os.getenv("DB_USER_NAME")
|
20 |
DB_PASSWORD = os.getenv("DB_PASSWORD")
|
21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
# Chat
|
24 |
openai_client = OpenAI(api_key=OPENAI_API_KEY)
|
@@ -49,112 +67,515 @@ def _add_question_vectorstore(question: str, response: str):
|
|
49 |
index.upsert([(vector_id, vector_embedding, vector_metadata)])
|
50 |
|
51 |
|
52 |
-
def _update_elements(question, chatbot, output, history_messages):
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
-
|
57 |
-
|
58 |
|
59 |
-
return chatbot
|
60 |
|
61 |
|
62 |
def _query_pinecone(embedding):
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
|
73 |
return final_results
|
74 |
|
75 |
|
76 |
def _general_prompt(context):
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
|
84 |
return context_prompt
|
85 |
|
86 |
|
87 |
def _call_embedding(text: str):
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
return response.data[0].embedding
|
93 |
|
94 |
|
95 |
def _call_gpt(prompt: str, message: str):
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
return response.choices[0].message.content
|
105 |
|
106 |
|
107 |
def _call_gpt_standalone(prompt: str):
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
return response.choices[0].message.content
|
116 |
|
117 |
|
118 |
def _get_standalone_question(question, history_messages):
|
119 |
-
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
|
122 |
-
history = ''
|
123 |
-
for i, msg in enumerate(history_messages):
|
124 |
try:
|
125 |
-
|
126 |
-
continue # Omit the prompt
|
127 |
-
if i % 2 == 0:
|
128 |
-
history += f'user: {msg["content"]}\n'
|
129 |
-
else:
|
130 |
-
history += f'assistant: {msg["content"]}\n'
|
131 |
except Exception as e:
|
132 |
print(e)
|
133 |
-
|
134 |
-
prompt_standalone = file_prompt_standalone.replace('HISTORY', history).replace('QUESTION', question)
|
135 |
-
standalone_msg_q = _call_gpt_standalone(prompt_standalone)
|
136 |
-
print(standalone_msg_q)
|
137 |
-
print("------------------")
|
138 |
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
|
142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
"""
|
144 |
Gets the answer of the chatbot
|
145 |
"""
|
|
|
146 |
if len(chatbot) == 8:
|
147 |
message_output = 'Un placer haberte ayudado, hasta luego!'
|
148 |
else:
|
|
|
149 |
standalone_msg_q = _get_standalone_question(question, history_messages) # create standalone question or message
|
|
|
|
|
|
|
|
|
150 |
output_embedding = _call_embedding(standalone_msg_q) # create embedding of standalone question or message
|
|
|
|
|
|
|
|
|
151 |
best_results = _query_pinecone(output_embedding) # get nearest embeddings
|
|
|
|
|
|
|
|
|
152 |
final_context_prompt = _general_prompt(best_results) # create context/general prompt
|
153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
|
155 |
if "Respuesta:" in message_output:
|
156 |
message_output.replace("Respuesta:", "")
|
157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
print(history_messages)
|
159 |
|
160 |
-
return _update_elements(question, chatbot, message_output, history_messages)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
+
import requests
|
3 |
import os
|
4 |
+
import time
|
5 |
+
from datetime import timedelta
|
6 |
from openai import OpenAI
|
7 |
from pinecone import Pinecone
|
8 |
import uuid
|
9 |
+
import re
|
10 |
+
import pandas as pd
|
11 |
+
import tensorflow as tf
|
12 |
+
from utils import create_folders
|
13 |
+
from google.cloud import storage
|
14 |
+
from elevenlabs.client import ElevenLabs, AsyncElevenLabs
|
15 |
+
from elevenlabs import play, save, Voice, stream
|
16 |
from pymongo.mongo_client import MongoClient
|
17 |
+
from gcp import download_credentials
|
18 |
from dotenv import load_dotenv
|
|
|
19 |
load_dotenv()
|
20 |
|
21 |
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
|
|
28 |
DB_USER_NAME = os.getenv("DB_USER_NAME")
|
29 |
DB_PASSWORD = os.getenv("DB_PASSWORD")
|
30 |
|
31 |
+
API_KEY_ELEVENLABS = os.getenv("API_KEY_ELEVENLABS")
|
32 |
+
|
33 |
+
D_ID_KEY = os.getenv("D_ID_KEY")
|
34 |
+
|
35 |
+
IMG_XAVY = os.getenv("IMG_XAVY")
|
36 |
+
|
37 |
+
CREDENTIALS_GCP = os.getenv("GOOGLE_APPLICATION_CREDENTIALS")
|
38 |
+
NAME_BUCKET = os.getenv("NAME_BUCKET")
|
39 |
+
|
40 |
|
41 |
# Chat
|
42 |
openai_client = OpenAI(api_key=OPENAI_API_KEY)
|
|
|
67 |
index.upsert([(vector_id, vector_embedding, vector_metadata)])
|
68 |
|
69 |
|
70 |
+
def _update_elements(question, chatbot, output, history_messages, url_audio, url_video, df_table_times):
|
71 |
+
|
72 |
+
if tf.test.is_gpu_available():
|
73 |
+
chatbot.append([question, output])
|
74 |
+
new_comp_audio = gr.Audio(value=str(url_audio), autoplay=False, label="Audio")
|
75 |
+
new_comp_video = gr.Video(value=str(url_video), autoplay=True, height=400, label="Video")
|
76 |
|
77 |
+
history_messages.append({'role': 'user', 'content': question})
|
78 |
+
history_messages.append({'role': 'assistant', 'content': output})
|
79 |
+
else:
|
80 |
+
chatbot.append([question, output])
|
81 |
+
new_comp_audio = gr.Audio(value=str(url_audio), autoplay=False, label="Audio")
|
82 |
+
new_comp_video = gr.Video(value=str(url_video), autoplay=True, height=400, label="Video")
|
83 |
|
84 |
+
history_messages.append({'role': 'user', 'content': question})
|
85 |
+
history_messages.append({'role': 'assistant', 'content': output})
|
86 |
|
87 |
+
return chatbot, new_comp_audio, new_comp_video, df_table_times
|
88 |
|
89 |
|
90 |
def _query_pinecone(embedding):
|
91 |
+
|
92 |
+
if tf.test.is_gpu_available():
|
93 |
+
results = index.query(
|
94 |
+
vector=embedding,
|
95 |
+
top_k=10,
|
96 |
+
include_metadata=True,
|
97 |
+
)
|
98 |
+
|
99 |
+
final_results = """"""
|
100 |
+
for result in results['matches']:
|
101 |
+
final_results += f"{result['metadata']['text']}\n"
|
102 |
+
else:
|
103 |
+
results = index.query(
|
104 |
+
vector=embedding,
|
105 |
+
top_k=10,
|
106 |
+
include_metadata=True,
|
107 |
+
)
|
108 |
|
109 |
+
final_results = """"""
|
110 |
+
for result in results['matches']:
|
111 |
+
final_results += f"{result['metadata']['text']}\n"
|
112 |
|
113 |
return final_results
|
114 |
|
115 |
|
116 |
def _general_prompt(context):
|
117 |
+
|
118 |
+
if tf.test.is_gpu_available():
|
119 |
+
with open("prompt_general.txt", "r") as file:
|
120 |
+
file_prompt = file.read().replace("\n", "")
|
121 |
+
|
122 |
+
context_prompt = file_prompt.replace('CONTEXT', context)
|
123 |
+
print(context_prompt)
|
124 |
+
print("--------------------")
|
125 |
+
else:
|
126 |
+
with open("prompt_general.txt", "r") as file:
|
127 |
+
file_prompt = file.read().replace("\n", "")
|
128 |
+
|
129 |
+
context_prompt = file_prompt.replace('CONTEXT', context)
|
130 |
+
print(context_prompt)
|
131 |
+
print("--------------------")
|
132 |
|
133 |
return context_prompt
|
134 |
|
135 |
|
136 |
def _call_embedding(text: str):
|
137 |
+
|
138 |
+
if tf.test.is_gpu_available():
|
139 |
+
response = openai_client.embeddings.create(
|
140 |
+
input=text,
|
141 |
+
model='text-embedding-ada-002'
|
142 |
+
)
|
143 |
+
else:
|
144 |
+
response = openai_client.embeddings.create(
|
145 |
+
input=text,
|
146 |
+
model='text-embedding-ada-002'
|
147 |
+
)
|
148 |
+
|
149 |
return response.data[0].embedding
|
150 |
|
151 |
|
152 |
def _call_gpt(prompt: str, message: str):
|
153 |
+
|
154 |
+
if tf.test.is_gpu_available():
|
155 |
+
response = openai_client.chat.completions.create(
|
156 |
+
model=MODEL_OPENAI,
|
157 |
+
temperature=0.2,
|
158 |
+
messages=[
|
159 |
+
{'role': 'system', 'content': prompt},
|
160 |
+
{'role': 'user', 'content': message}
|
161 |
+
]
|
162 |
+
)
|
163 |
+
else:
|
164 |
+
response = openai_client.chat.completions.create(
|
165 |
+
model=MODEL_OPENAI,
|
166 |
+
temperature=0.2,
|
167 |
+
messages=[
|
168 |
+
{'role': 'system', 'content': prompt},
|
169 |
+
{'role': 'user', 'content': message}
|
170 |
+
]
|
171 |
+
)
|
172 |
+
|
173 |
return response.choices[0].message.content
|
174 |
|
175 |
|
176 |
def _call_gpt_standalone(prompt: str):
|
177 |
+
|
178 |
+
if tf.test.is_gpu_available():
|
179 |
+
response = openai_client.chat.completions.create(
|
180 |
+
model=MODEL_OPENAI,
|
181 |
+
temperature=0.2,
|
182 |
+
messages=[
|
183 |
+
{'role': 'system', 'content': prompt},
|
184 |
+
]
|
185 |
+
)
|
186 |
+
else:
|
187 |
+
response = openai_client.chat.completions.create(
|
188 |
+
model=MODEL_OPENAI,
|
189 |
+
temperature=0.2,
|
190 |
+
messages=[
|
191 |
+
{'role': 'system', 'content': prompt},
|
192 |
+
]
|
193 |
+
)
|
194 |
+
|
195 |
return response.choices[0].message.content
|
196 |
|
197 |
|
198 |
def _get_standalone_question(question, history_messages):
|
199 |
+
|
200 |
+
if tf.test.is_gpu_available():
|
201 |
+
with open("prompt_standalone_message.txt", "r") as file:
|
202 |
+
file_prompt_standalone = file.read().replace("\n", "")
|
203 |
+
|
204 |
+
history = ''
|
205 |
+
for i, msg in enumerate(history_messages):
|
206 |
+
try:
|
207 |
+
if i == 0:
|
208 |
+
continue # Omit the prompt
|
209 |
+
if i % 2 == 0:
|
210 |
+
history += f'user: {msg["content"]}\n'
|
211 |
+
else:
|
212 |
+
history += f'assistant: {msg["content"]}\n'
|
213 |
+
except Exception as e:
|
214 |
+
print(e)
|
215 |
+
|
216 |
+
prompt_standalone = file_prompt_standalone.replace('HISTORY', history).replace('QUESTION', question)
|
217 |
+
standalone_msg_q = _call_gpt_standalone(prompt_standalone)
|
218 |
+
print(standalone_msg_q)
|
219 |
+
print("------------------")
|
220 |
+
else:
|
221 |
+
with open("prompt_standalone_message.txt", "r") as file:
|
222 |
+
file_prompt_standalone = file.read().replace("\n", "")
|
223 |
+
|
224 |
+
history = ''
|
225 |
+
for i, msg in enumerate(history_messages):
|
226 |
+
try:
|
227 |
+
if i == 0:
|
228 |
+
continue # Omit the prompt
|
229 |
+
if i % 2 == 0:
|
230 |
+
history += f'user: {msg["content"]}\n'
|
231 |
+
else:
|
232 |
+
history += f'assistant: {msg["content"]}\n'
|
233 |
+
except Exception as e:
|
234 |
+
print(e)
|
235 |
+
|
236 |
+
prompt_standalone = file_prompt_standalone.replace('HISTORY', history).replace('QUESTION', question)
|
237 |
+
standalone_msg_q = _call_gpt_standalone(prompt_standalone)
|
238 |
+
print(standalone_msg_q)
|
239 |
+
print("------------------")
|
240 |
+
|
241 |
+
return standalone_msg_q
|
242 |
+
|
243 |
+
|
244 |
+
def _create_clean_message(text: str):
|
245 |
+
clean_answer = re.sub(r'http[s]?://\S+', 'el siguiente link', text)
|
246 |
+
return clean_answer
|
247 |
+
|
248 |
+
|
249 |
+
def _create_audio(clean_text: str):
|
250 |
+
|
251 |
+
if tf.test.is_gpu_available():
|
252 |
+
download_credentials()
|
253 |
+
create_folders()
|
254 |
+
STORAGE_CLIENT = storage.Client.from_service_account_json(CREDENTIALS_GCP)
|
255 |
+
|
256 |
+
unique_id = str(uuid.uuid4())
|
257 |
+
|
258 |
+
# Create audio file
|
259 |
+
client_elevenlabs = ElevenLabs(api_key=API_KEY_ELEVENLABS)
|
260 |
+
voice_custom = Voice(voice_id = "ZQe5CZNOzWyzPSCn5a3c")
|
261 |
+
|
262 |
+
audio = client_elevenlabs.generate(
|
263 |
+
text=clean_text,
|
264 |
+
voice=voice_custom,
|
265 |
+
model="eleven_multilingual_v2"
|
266 |
+
)
|
267 |
+
|
268 |
+
source_audio_file_name = f'./audios/file_audio_{unique_id}.wav'
|
269 |
|
|
|
|
|
270 |
try:
|
271 |
+
save(audio, source_audio_file_name)
|
|
|
|
|
|
|
|
|
|
|
272 |
except Exception as e:
|
273 |
print(e)
|
|
|
|
|
|
|
|
|
|
|
274 |
|
275 |
+
# Save audio and get url of gcp
|
276 |
+
destination_blob_name_audio = unique_id + '.wav'
|
277 |
+
|
278 |
+
bucket = STORAGE_CLIENT.bucket(NAME_BUCKET)
|
279 |
+
blob = bucket.blob(destination_blob_name_audio)
|
280 |
+
try:
|
281 |
+
blob.upload_from_filename(source_audio_file_name)
|
282 |
+
except Exception as e:
|
283 |
+
print(e)
|
284 |
|
285 |
+
signed_url_audio = "None"
|
286 |
+
try:
|
287 |
+
url_expiration = timedelta(minutes=15)
|
288 |
+
signed_url_audio = blob.generate_signed_url(expiration=url_expiration)
|
289 |
+
except Exception as e:
|
290 |
+
print(e)
|
291 |
+
else:
|
292 |
+
download_credentials()
|
293 |
+
create_folders()
|
294 |
+
STORAGE_CLIENT = storage.Client.from_service_account_json(CREDENTIALS_GCP)
|
295 |
|
296 |
+
unique_id = str(uuid.uuid4())
|
297 |
+
|
298 |
+
# Create audio file
|
299 |
+
client_elevenlabs = ElevenLabs(api_key=API_KEY_ELEVENLABS)
|
300 |
+
voice_custom = Voice(voice_id = "ZQe5CZNOzWyzPSCn5a3c")
|
301 |
+
|
302 |
+
audio = client_elevenlabs.generate(
|
303 |
+
text=clean_text,
|
304 |
+
voice=voice_custom,
|
305 |
+
model="eleven_multilingual_v2"
|
306 |
+
)
|
307 |
+
|
308 |
+
source_audio_file_name = f'./audios/file_audio_{unique_id}.wav'
|
309 |
+
|
310 |
+
try:
|
311 |
+
save(audio, source_audio_file_name)
|
312 |
+
except Exception as e:
|
313 |
+
print(e)
|
314 |
+
|
315 |
+
# Save audio and get url of gcp
|
316 |
+
destination_blob_name_audio = unique_id + '.wav'
|
317 |
+
|
318 |
+
bucket = STORAGE_CLIENT.bucket(NAME_BUCKET)
|
319 |
+
blob = bucket.blob(destination_blob_name_audio)
|
320 |
+
try:
|
321 |
+
blob.upload_from_filename(source_audio_file_name)
|
322 |
+
except Exception as e:
|
323 |
+
print(e)
|
324 |
+
|
325 |
+
signed_url_audio = "None"
|
326 |
+
try:
|
327 |
+
url_expiration = timedelta(minutes=15)
|
328 |
+
signed_url_audio = blob.generate_signed_url(expiration=url_expiration)
|
329 |
+
except Exception as e:
|
330 |
+
print(e)
|
331 |
+
|
332 |
+
return signed_url_audio, unique_id
|
333 |
+
|
334 |
+
|
335 |
+
def _create_video(link_audio: str, unique_id: str):
|
336 |
+
|
337 |
+
if tf.test.is_gpu_available():
|
338 |
+
STORAGE_CLIENT = storage.Client.from_service_account_json(CREDENTIALS_GCP)
|
339 |
+
bucket = STORAGE_CLIENT.bucket(NAME_BUCKET)
|
340 |
+
|
341 |
+
# Create video talk with file audio created by elevenlabs api
|
342 |
+
url_did = "https://api.d-id.com/talks"
|
343 |
+
|
344 |
+
payload = {
|
345 |
+
"script": {
|
346 |
+
"type": "audio",
|
347 |
+
"provider": {
|
348 |
+
"type": "microsoft",
|
349 |
+
"voice_id": "en-US-JennyNeural"
|
350 |
+
},
|
351 |
+
"ssml": "false",
|
352 |
+
"audio_url": link_audio
|
353 |
+
},
|
354 |
+
"config": {
|
355 |
+
"fluent": "false",
|
356 |
+
"pad_audio": "0.0",
|
357 |
+
"stitch": True
|
358 |
+
},
|
359 |
+
"source_url": IMG_XAVY
|
360 |
+
}
|
361 |
+
headers = {
|
362 |
+
"accept": "application/json",
|
363 |
+
"content-type": "application/json",
|
364 |
+
"authorization": f"Basic {D_ID_KEY}"
|
365 |
+
}
|
366 |
+
|
367 |
+
request_create_talk = requests.post(url_did, json=payload, headers=headers)
|
368 |
+
resp_create_talk = request_create_talk.json()
|
369 |
+
|
370 |
+
talk_id = "None"
|
371 |
+
try:
|
372 |
+
talk_id = resp_create_talk['id']
|
373 |
+
except Exception as e:
|
374 |
+
print(e)
|
375 |
+
|
376 |
+
# Get url of video file
|
377 |
+
url_get_talk_id = f"https://api.d-id.com/talks/{talk_id}"
|
378 |
+
|
379 |
+
|
380 |
+
while True:
|
381 |
+
request_video_url = requests.get(url_get_talk_id, headers=headers)
|
382 |
+
resp_video_url = request_video_url.json()
|
383 |
+
|
384 |
+
if resp_video_url['status'] == 'done':
|
385 |
+
break
|
386 |
+
# Sleep until the video is ready
|
387 |
+
time.sleep(0.5)
|
388 |
+
|
389 |
+
result_url_video = resp_video_url['result_url']
|
390 |
+
|
391 |
+
# Saves the video into a file to later upload it to the GCP
|
392 |
+
source_video_file_name = f'./videos/video_final_{unique_id}.mp4'
|
393 |
+
request_video = requests.get(result_url_video)
|
394 |
+
if request_video.status_code == 200:
|
395 |
+
with open(source_video_file_name, 'wb') as outfile:
|
396 |
+
outfile.write(request_video.content)
|
397 |
+
|
398 |
+
# Save video file to the GCP
|
399 |
+
destination_blob_name_video = unique_id + '.mp4'
|
400 |
+
|
401 |
+
# Configure bucket
|
402 |
+
blob = bucket.blob(destination_blob_name_video)
|
403 |
+
try:
|
404 |
+
blob.upload_from_filename(source_video_file_name)
|
405 |
+
except Exception as e:
|
406 |
+
print(e)
|
407 |
+
|
408 |
+
signed_url_video = "None"
|
409 |
+
try:
|
410 |
+
url_expiration_video = timedelta(minutes=15)
|
411 |
+
signed_url_video = blob.generate_signed_url(expiration=url_expiration_video)
|
412 |
+
except Exception as e:
|
413 |
+
print(e)
|
414 |
+
else:
|
415 |
+
STORAGE_CLIENT = storage.Client.from_service_account_json(CREDENTIALS_GCP)
|
416 |
+
bucket = STORAGE_CLIENT.bucket(NAME_BUCKET)
|
417 |
+
|
418 |
+
# Create video talk with file audio created by elevenlabs api
|
419 |
+
url_did = "https://api.d-id.com/talks"
|
420 |
+
|
421 |
+
payload = {
|
422 |
+
"script": {
|
423 |
+
"type": "audio",
|
424 |
+
"provider": {
|
425 |
+
"type": "microsoft",
|
426 |
+
"voice_id": "en-US-JennyNeural"
|
427 |
+
},
|
428 |
+
"ssml": "false",
|
429 |
+
"audio_url": link_audio
|
430 |
+
},
|
431 |
+
"config": {
|
432 |
+
"fluent": "false",
|
433 |
+
"pad_audio": "0.0",
|
434 |
+
"stitch": True
|
435 |
+
},
|
436 |
+
"source_url": IMG_XAVY
|
437 |
+
}
|
438 |
+
headers = {
|
439 |
+
"accept": "application/json",
|
440 |
+
"content-type": "application/json",
|
441 |
+
"authorization": f"Basic {D_ID_KEY}"
|
442 |
+
}
|
443 |
+
|
444 |
+
request_create_talk = requests.post(url_did, json=payload, headers=headers)
|
445 |
+
resp_create_talk = request_create_talk.json()
|
446 |
+
|
447 |
+
talk_id = "None"
|
448 |
+
try:
|
449 |
+
talk_id = resp_create_talk['id']
|
450 |
+
except Exception as e:
|
451 |
+
print(e)
|
452 |
+
|
453 |
+
# Get url of video file
|
454 |
+
url_get_talk_id = f"https://api.d-id.com/talks/{talk_id}"
|
455 |
+
|
456 |
+
|
457 |
+
while True:
|
458 |
+
request_video_url = requests.get(url_get_talk_id, headers=headers)
|
459 |
+
resp_video_url = request_video_url.json()
|
460 |
+
|
461 |
+
if resp_video_url['status'] == 'done':
|
462 |
+
break
|
463 |
+
# Sleep until the video is ready
|
464 |
+
time.sleep(0.5)
|
465 |
+
|
466 |
+
result_url_video = resp_video_url['result_url']
|
467 |
+
|
468 |
+
# Saves the video into a file to later upload it to the GCP
|
469 |
+
source_video_file_name = f'./videos/video_final_{unique_id}.mp4'
|
470 |
+
request_video = requests.get(result_url_video)
|
471 |
+
if request_video.status_code == 200:
|
472 |
+
with open(source_video_file_name, 'wb') as outfile:
|
473 |
+
outfile.write(request_video.content)
|
474 |
+
|
475 |
+
# Save video file to the GCP
|
476 |
+
destination_blob_name_video = unique_id + '.mp4'
|
477 |
+
|
478 |
+
# Configure bucket
|
479 |
+
blob = bucket.blob(destination_blob_name_video)
|
480 |
+
try:
|
481 |
+
blob.upload_from_filename(source_video_file_name)
|
482 |
+
except Exception as e:
|
483 |
+
print(e)
|
484 |
+
|
485 |
+
signed_url_video = "None"
|
486 |
+
try:
|
487 |
+
url_expiration_video = timedelta(minutes=15)
|
488 |
+
signed_url_video = blob.generate_signed_url(expiration=url_expiration_video)
|
489 |
+
except Exception as e:
|
490 |
+
print(e)
|
491 |
+
|
492 |
+
return signed_url_video
|
493 |
+
|
494 |
+
|
495 |
+
def get_answer(question: str, chatbot: list[tuple[str, str]], history_messages, comp_audio, comp_video, df_table):
|
496 |
"""
|
497 |
Gets the answer of the chatbot
|
498 |
"""
|
499 |
+
|
500 |
if len(chatbot) == 8:
|
501 |
message_output = 'Un placer haberte ayudado, hasta luego!'
|
502 |
else:
|
503 |
+
start_get_standalone_question = time.time()
|
504 |
standalone_msg_q = _get_standalone_question(question, history_messages) # create standalone question or message
|
505 |
+
end_get_standalone_question = time.time()
|
506 |
+
time_get_standalone_question = end_get_standalone_question - start_get_standalone_question
|
507 |
+
|
508 |
+
start_call_embedding = time.time()
|
509 |
output_embedding = _call_embedding(standalone_msg_q) # create embedding of standalone question or message
|
510 |
+
end_call_embedding = time.time()
|
511 |
+
time_call_embedding = end_call_embedding - start_call_embedding
|
512 |
+
|
513 |
+
start_query_pinecone = time.time()
|
514 |
best_results = _query_pinecone(output_embedding) # get nearest embeddings
|
515 |
+
end_query_pinecone = time.time()
|
516 |
+
time_query_pinecone = end_query_pinecone - start_query_pinecone
|
517 |
+
|
518 |
+
start_general_prompt = time.time()
|
519 |
final_context_prompt = _general_prompt(best_results) # create context/general prompt
|
520 |
+
end_general_prompt = time.time()
|
521 |
+
time_general_prompt = end_general_prompt - start_general_prompt
|
522 |
+
|
523 |
+
start_call_gpt = time.time()
|
524 |
+
message_output = _call_gpt(final_context_prompt, question) # final response (to user)
|
525 |
+
end_call_gpt = time.time()
|
526 |
+
time_call_gpt = end_call_gpt - start_call_gpt
|
527 |
|
528 |
if "Respuesta:" in message_output:
|
529 |
message_output.replace("Respuesta:", "")
|
530 |
|
531 |
+
start_create_clean_message = time.time()
|
532 |
+
processed_message = _create_clean_message(message_output) # clean message output
|
533 |
+
end_create_clean_message = time.time()
|
534 |
+
time_create_clean_message = end_create_clean_message - start_create_clean_message
|
535 |
+
|
536 |
+
start_create_audio = time.time()
|
537 |
+
url_audio, unique_id = _create_audio(processed_message) # create audio with elevenlabs
|
538 |
+
end_create_audio = time.time()
|
539 |
+
time_create_audio = end_create_audio - start_create_audio
|
540 |
+
|
541 |
+
start_create_video = time.time()
|
542 |
+
url_video = _create_video(url_audio, unique_id) # create video with d-id no streaming
|
543 |
+
end_create_video = time.time()
|
544 |
+
time_create_video = end_create_video - start_create_video
|
545 |
+
|
546 |
+
final_time = time_get_standalone_question + time_call_embedding + time_query_pinecone + time_general_prompt
|
547 |
+
final_time += (time_call_gpt + time_create_clean_message + time_create_audio + time_create_video)
|
548 |
+
|
549 |
+
df_table = pd.DataFrame(df_table)
|
550 |
+
df_table.loc[len(df_table.index)] = [question,
|
551 |
+
message_output,
|
552 |
+
time_get_standalone_question,
|
553 |
+
time_call_embedding,
|
554 |
+
time_query_pinecone,
|
555 |
+
time_general_prompt,
|
556 |
+
time_call_gpt,
|
557 |
+
time_create_clean_message,
|
558 |
+
time_create_audio,
|
559 |
+
time_create_video,
|
560 |
+
final_time]
|
561 |
+
|
562 |
+
new_df_table = gr.DataFrame(df_table, interactive=False, visible=True)
|
563 |
+
|
564 |
print(history_messages)
|
565 |
|
566 |
+
return _update_elements(question, chatbot, message_output, history_messages, url_audio, url_video, new_df_table)
|
567 |
+
|
568 |
+
|
569 |
+
def init_greeting(chatbot, history_messages):
|
570 |
+
if len(chatbot) == 0:
|
571 |
+
greeting = ('Hola 👋, soy Roll, tu asistente de recomendación de series y películas animadas en Crunchyroll. ¿En qué puedo ayudarte hoy?')
|
572 |
+
history_messages.append({'role': 'assistant', 'content': greeting})
|
573 |
+
chatbot.append([None, greeting])
|
574 |
+
|
575 |
+
return chatbot, history_messages
|
576 |
+
|
577 |
+
|
578 |
+
def export_dataframe(df):
|
579 |
+
final_df = pd.DataFrame(df)
|
580 |
+
final_df = final_df.iloc[1:]
|
581 |
+
final_df.to_csv("./csv_times/csv_times.csv", index=False, encoding='utf-8')
|
gcp.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from pathlib import Path
|
3 |
+
from datetime import timedelta
|
4 |
+
from google.cloud import storage
|
5 |
+
from huggingface_hub import hf_hub_download
|
6 |
+
from google.cloud.storage import transfer_manager
|
7 |
+
from dotenv import load_dotenv
|
8 |
+
load_dotenv()
|
9 |
+
|
10 |
+
REPO_HUGGING = os.getenv("REPO_HUGGING")
|
11 |
+
HUB_TOKEN = os.getenv("HUB_TOKEN")
|
12 |
+
|
13 |
+
def download_credentials() -> None:
|
14 |
+
"""
|
15 |
+
Downloads the GCP credentials from Hugging Face Hub
|
16 |
+
"""
|
17 |
+
assets_dir = 'assets'
|
18 |
+
credentials_file = os.path.join(assets_dir, "credentials.json")
|
19 |
+
|
20 |
+
# Verificar si la carpeta 'assets' existe y crearla si no
|
21 |
+
os.makedirs(assets_dir, exist_ok=True)
|
22 |
+
|
23 |
+
# Verificar si el archivo 'credentials.json' ya existe en la carpeta 'assets'
|
24 |
+
if not os.path.isfile(credentials_file):
|
25 |
+
hf_hub_download(
|
26 |
+
repo_id=REPO_HUGGING, repo_type='dataset', filename="credentials.json",
|
27 |
+
token=HUB_TOKEN, local_dir=assets_dir
|
28 |
+
)
|
utils.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
import gradio as gr
|
|
|
2 |
|
3 |
def make_invisible():
|
4 |
"""
|
@@ -12,3 +13,21 @@ def make_visible():
|
|
12 |
Makes visibles a rows
|
13 |
"""
|
14 |
return gr.Row.update(visible=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
+
import os
|
3 |
|
4 |
def make_invisible():
|
5 |
"""
|
|
|
13 |
Makes visibles a rows
|
14 |
"""
|
15 |
return gr.Row.update(visible=True)
|
16 |
+
|
17 |
+
|
18 |
+
def create_folders():
|
19 |
+
"""
|
20 |
+
Creates 'audios' and 'videos' directories if they do not exist
|
21 |
+
"""
|
22 |
+
audio_dir = 'audios'
|
23 |
+
video_dir = 'videos'
|
24 |
+
times_dir = 'csv_times'
|
25 |
+
|
26 |
+
if not os.path.exists(audio_dir):
|
27 |
+
os.makedirs(audio_dir)
|
28 |
+
|
29 |
+
if not os.path.exists(video_dir):
|
30 |
+
os.makedirs(video_dir)
|
31 |
+
|
32 |
+
if not os.path.exists(times_dir):
|
33 |
+
os.makedirs(times_dir)
|