Spaces:
Sleeping
Sleeping
Rename alanvideos_final.py to app.py
Browse files- alanvideos_final.py +0 -278
- app.py +262 -0
alanvideos_final.py
DELETED
@@ -1,278 +0,0 @@
|
|
1 |
-
# -*- coding: utf-8 -*-
|
2 |
-
"""AlanVideos FINAL.ipynb
|
3 |
-
|
4 |
-
Automatically generated by Colab.
|
5 |
-
|
6 |
-
Original file is located at
|
7 |
-
https://colab.research.google.com/drive/1dMbuk4RyLyFp1-DhetRxkP8vB_TdTszO
|
8 |
-
"""
|
9 |
-
|
10 |
-
!pip install -q -r requirements.txt
|
11 |
-
|
12 |
-
# Commented out IPython magic to ensure Python compatibility.
|
13 |
-
# %%writefile app.py
|
14 |
-
#
|
15 |
-
# import os
|
16 |
-
# import re
|
17 |
-
# import streamlit as st
|
18 |
-
# import transformers
|
19 |
-
# from transformers import pipeline
|
20 |
-
# from transformers import AutoTokenizer
|
21 |
-
# import nltk
|
22 |
-
# from PIL import Image
|
23 |
-
# import torch
|
24 |
-
# import ffmpeg
|
25 |
-
# import speech_recognition as sr
|
26 |
-
# from pytube import YouTube
|
27 |
-
# import string
|
28 |
-
# import whisper
|
29 |
-
# from moviepy.editor import AudioFileClip
|
30 |
-
# from langchain.text_splitter import CharacterTextSplitter
|
31 |
-
# from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
|
32 |
-
# from langchain.embeddings import OpenAIEmbeddings
|
33 |
-
# from langchain.vectorstores import FAISS
|
34 |
-
# from langchain.chat_models import ChatOpenAI
|
35 |
-
# from langchain.memory import ConversationBufferWindowMemory
|
36 |
-
# from langchain.chains import ConversationalRetrievalChain
|
37 |
-
# from langchain.callbacks import get_openai_callback
|
38 |
-
# from key import openai_api_key
|
39 |
-
# from langchain import PromptTemplate
|
40 |
-
# from langchain import LLMChain
|
41 |
-
# os.environ['OPENAI_API_KEY'] = openai_api_key
|
42 |
-
#
|
43 |
-
#
|
44 |
-
# # Criando a função que corta o texto em chunks:
|
45 |
-
# def get_chunks(texto_transcrito):
|
46 |
-
# """Função que recebe uma string (um texto transcrito) e devolve
|
47 |
-
# uma lista de strings, em que cada string ("chunk") contém um
|
48 |
-
# tamanho específico, com overlap entre os pedaços. """
|
49 |
-
# text_splitter=CharacterTextSplitter(separator='.', chunk_size=1000, chunk_overlap=100, length_function=len)
|
50 |
-
# chunks = text_splitter.split_text(texto_transcrito)
|
51 |
-
# return chunks
|
52 |
-
#
|
53 |
-
# # Criando a função de vectorstore para transformar os chunks de texto em embeddings:
|
54 |
-
# def get_vectorstore(chunks):
|
55 |
-
# """Função que recebe uma lista de chunks de texto e
|
56 |
-
# os converte em embeddings (representações numéricas)
|
57 |
-
# usando um modelo de embeddings pré-treinado. """
|
58 |
-
# embeddings = OpenAIEmbeddings()
|
59 |
-
# vectorstore = FAISS.from_texts(texts=chunks, embedding=embeddings)
|
60 |
-
# return vectorstore
|
61 |
-
#
|
62 |
-
#
|
63 |
-
# # Criando a função para converter o vídeo para o formato adequado:
|
64 |
-
# @st.cache_data
|
65 |
-
# def convert_mp4_to_wav(mp4_file, wav_file):
|
66 |
-
# """Função que converte um arquivo de vídeo no formato MP4 para um arquivo de
|
67 |
-
# áudio no formato WAV a partir das seguintes entradas: o caminho do arquivo
|
68 |
-
# de vídeo no formato MP4 que se deseja converter; o caminho onde o arquivo
|
69 |
-
# de áudio WAV resultante será salvo. Nenhuma saída explícita é retornada."""
|
70 |
-
# video = AudioFileClip(mp4_file)
|
71 |
-
# video.write_audiofile(wav_file)
|
72 |
-
#
|
73 |
-
# # Criando a função que gera a transcrição:
|
74 |
-
# @st.cache_data
|
75 |
-
# def get_transcriptions(url):
|
76 |
-
# """ Função que recebe um link de um vídeo no YouTube e
|
77 |
-
# devolve um dicionário contendo o título do vídeo (key)
|
78 |
-
# e a transcrição de seu áudio (value). """
|
79 |
-
# dicionario = {}
|
80 |
-
# # Baixando o áudio:
|
81 |
-
# youtube_content = YouTube(url)
|
82 |
-
# audio_streams = youtube_content.streams.filter(only_audio=True)
|
83 |
-
# audio_streams[0].download()
|
84 |
-
# title = youtube_content.title
|
85 |
-
# # Convertendo para Wav:
|
86 |
-
# mp4_file = '/content/'+''.join(char for char in title if char not in string.punctuation.replace('/', '').replace('-', '').replace('!', '').replace('(', '').replace(')', ''))+'.mp4'
|
87 |
-
# wav_file = '/content/'+''.join(char for char in title if char not in string.punctuation.replace('/', '').replace('-', '').replace('!', '').replace('(', '').replace(')', ''))+'.wav'
|
88 |
-
# convert_mp4_to_wav(mp4_file, wav_file)
|
89 |
-
# # Inicializando o reconhecedor de fala:
|
90 |
-
# r = sr.Recognizer()
|
91 |
-
# # Carregando o áudio gravado pelo Whisper em um objeto de áudio:
|
92 |
-
# with sr.AudioFile(wav_file) as source:
|
93 |
-
# audio = r.record(source)
|
94 |
-
# # Transcrevendo:
|
95 |
-
# texto_transcrito = r.recognize_whisper(audio)
|
96 |
-
# # Adicionando ao dicionario:
|
97 |
-
# dicionario[title] = texto_transcrito
|
98 |
-
# return dicionario
|
99 |
-
#
|
100 |
-
#
|
101 |
-
# # Criando a função que carrega o sumarizador extrativo (para português e inglês) via HuggingFace:
|
102 |
-
# @st.cache_resource
|
103 |
-
# def load_extractive():
|
104 |
-
# """ Função sem valores de entrada que carrega o modelo
|
105 |
-
# de sumarização extrativa via HuggingFace. """
|
106 |
-
# return pipeline("summarization", model="NotXia/longformer-bio-ext-summ", tokenizer=AutoTokenizer.from_pretrained("NotXia/longformer-bio-ext-summ"), trust_remote_code=True)
|
107 |
-
#
|
108 |
-
# # Criando a função que gera a sumarização extrativa:
|
109 |
-
# @st.cache_data
|
110 |
-
# def get_summarization(_model_pipeline, full_text, ratio):
|
111 |
-
# """ Função que recebe um texto completo a ser resumido, juntamente
|
112 |
-
# à taxa desejada de sumarização e a pipeline do modelo que fará o
|
113 |
-
# sumário, e devolve a versão resumida desse texto. """
|
114 |
-
# sentences = nltk.sent_tokenize(full_text)
|
115 |
-
# extractive_sentences = _model_pipeline({"sentences": sentences}, strategy="ratio", strategy_args=ratio)
|
116 |
-
# extractive_text = " ".join(extractive_sentences[0])
|
117 |
-
# return extractive_text
|
118 |
-
#
|
119 |
-
#
|
120 |
-
# # Criando a função que gera a tradução do texto a partir do ChatGPT:
|
121 |
-
# @st.cache_data
|
122 |
-
# def get_translation(summarized_text):
|
123 |
-
# """ Função que recebe um resumo a ser traduzido,
|
124 |
-
# juntamente à pipeline do modelo que fará a tradução,
|
125 |
-
# e devolve a versão traduzida do texto. """
|
126 |
-
# LLM = ChatOpenAI(openai_api_key=openai_api_key, temperature=0.25, model_name="gpt-3.5-turbo")
|
127 |
-
# messages = [SystemMessage(content='Você é um especialista em traduções de texto do inglês para português'), HumanMessage(content=summarized_text)]
|
128 |
-
# translation = LLM(messages)
|
129 |
-
# return translation.content
|
130 |
-
#
|
131 |
-
#
|
132 |
-
# # Criando a função que corrige os erros de transcrição do texto a partir do ChatGPT:
|
133 |
-
# @st.cache_data
|
134 |
-
# def get_correction(transcription):
|
135 |
-
# """ Função que recebe a transcrição (em PT-BR) e corrige eventuais
|
136 |
-
# erros do whisper - por exemplo, a troca de palavras que, embora
|
137 |
-
# semelhantes na pronúncia, são totalmente absurdas no contexto. """
|
138 |
-
# correction_prompt = PromptTemplate.from_template(template = 'Você é um especialista em correção de textos. Você receberá uma transcrição de um áudio e deverá substituir as palavras transcritas erroneamente, considerando apenas a pronúncia, por palavras adequadas que façam sentido no contexto do texto. Além disso, corrija questões gramáticais para facilitar a compreensão. Corrija a seguinte transcrição: {transcription}')
|
139 |
-
# LLM = ChatOpenAI(openai_api_key=openai_api_key, temperature=0.1, model_name="gpt-3.5-turbo")
|
140 |
-
# corrector = LLMChain(prompt=correction_prompt, llm=LLM)
|
141 |
-
# with get_openai_callback() as cb:
|
142 |
-
# corrected_transcription = corrector.run({"transcription": transcription})
|
143 |
-
# total_t = cb.total_tokens
|
144 |
-
# prompt_t = cb.prompt_tokens
|
145 |
-
# completion_t = cb.completion_tokens
|
146 |
-
# total_cost = cb.total_cost
|
147 |
-
# return corrected_transcription
|
148 |
-
#
|
149 |
-
#
|
150 |
-
# # Criando o chatbot
|
151 |
-
# def alan_videos(vectorstore):
|
152 |
-
# """ Função que inicializa e configura um LLM da OpenAI
|
153 |
-
# e retorna um chatbot configurado pronto para uso. """
|
154 |
-
# memory = ConversationBufferWindowMemory(memory_key='chat_history', return_messages=True, k=3)
|
155 |
-
# LLM = ChatOpenAI(openai_api_key=openai_api_key, temperature=0.25, model_name="gpt-3.5-turbo")
|
156 |
-
# retriever=vectorstore.as_retriever()
|
157 |
-
# chatbot = ConversationalRetrievalChain.from_llm(llm=LLM, retriever=retriever, memory=memory)
|
158 |
-
# return chatbot
|
159 |
-
#
|
160 |
-
# # Criando um modelo de chat:
|
161 |
-
# def chat(pergunta):
|
162 |
-
# """ Função que processa uma pergunta utilizando o chatbot
|
163 |
-
# configurado (alan_videos) e retorna sua resposta. """
|
164 |
-
# with get_openai_callback() as cb:
|
165 |
-
# resposta = st.session_state.alanvideos.invoke({"question": pergunta})
|
166 |
-
# total_t = cb.total_tokens
|
167 |
-
# prompt_t = cb.prompt_tokens
|
168 |
-
# completion_t = cb.completion_tokens
|
169 |
-
# total_cost = cb.total_cost
|
170 |
-
# return resposta['answer']
|
171 |
-
#
|
172 |
-
#
|
173 |
-
# # Criando a função para customização com CSS:
|
174 |
-
# def local_css(file_name):
|
175 |
-
# """ Função que carrega um arquivo CSS local e aplica o estilo
|
176 |
-
# ao Streamlit app, personalizando a interface do usuário. """
|
177 |
-
# with open(file_name, "r") as f:
|
178 |
-
# st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
|
179 |
-
#
|
180 |
-
# # Configurando a aba do site:
|
181 |
-
# icon = Image.open("Traçado laranja #f1863d.png")
|
182 |
-
# st.set_page_config(page_title="AlanVideos", page_icon=icon, layout="wide", initial_sidebar_state="auto")
|
183 |
-
#
|
184 |
-
#
|
185 |
-
# # Configurando o site:
|
186 |
-
# def main():
|
187 |
-
# local_css("style.css")
|
188 |
-
#
|
189 |
-
# header = st.container()
|
190 |
-
# model = st.container()
|
191 |
-
# model_1 = st.container()
|
192 |
-
# model_2 = st.container()
|
193 |
-
#
|
194 |
-
# # Configurando a barra lateral:
|
195 |
-
# with st.sidebar:
|
196 |
-
# with st.form("data_collection"):
|
197 |
-
# link = st.text_area(label="Coloque o link do seu vídeo do YouTube:", height=25, placeholder="Digite seu link...")
|
198 |
-
# language = st.selectbox('Qual a linguagem do seu vídeo?', ('Português (pt)', 'Inglês (en)'))
|
199 |
-
# translate = st.selectbox('Você deseja que o seu vídeo seja traduzido para Português?', ('Não', 'Sim'))
|
200 |
-
# compression_rate = st.slider(label="Selecione o percentual de sumarização:", min_value=0.05, max_value=0.50, value=0.25, step=0.05)
|
201 |
-
# submitted = st.form_submit_button("Enviar")
|
202 |
-
#
|
203 |
-
# # Verificando se o link do vídeo é válido:
|
204 |
-
# if link != '':
|
205 |
-
# if re.match((r'(https?://)?(www\.)?''(youtube|youtu|youtube-nocookie)\.(com|be)/''(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})'), link):
|
206 |
-
# st.success('Dados coletados!', icon="✅")
|
207 |
-
# else:
|
208 |
-
# st.error('Link inválido. Por favor, insira um link do YouTube.', icon="🚨")
|
209 |
-
#
|
210 |
-
# if "alanvideos" not in st.session_state:
|
211 |
-
# st.session_state.alanvideos = None
|
212 |
-
#
|
213 |
-
# # Configurando o cabeçalho:
|
214 |
-
# with header:
|
215 |
-
# st.title(":orange[Alan]Chat")
|
216 |
-
# st.subheader("Olá, usuário! Este é um projeto que utiliza técnicas de inteligência artificial para simplificar e acelerar a compreensão de conteúdo audiovisual. Por favor, preencha o formulário ao lado para que possamos responder as suas dúvidas a respeito de um vídeo do YouTube! :)", divider = "orange")
|
217 |
-
#
|
218 |
-
# # Configurando os modelos:
|
219 |
-
# with model:
|
220 |
-
# if submitted and re.match((r'(https?://)?(www\.)?''(youtube|youtu|youtube-nocookie)\.(com|be)/''(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})'), link):
|
221 |
-
# with st.spinner("Carregando modelos..."):
|
222 |
-
# nltk.download("punkt")
|
223 |
-
# extractive = load_extractive()
|
224 |
-
# with st.spinner("Transcrevendo texto..."):
|
225 |
-
# transcription = get_transcriptions(link)
|
226 |
-
# texto_cru = ''.join(list(transcription.values()))
|
227 |
-
# # Preparando o modelo de sumarização após o envio de um link:
|
228 |
-
# with model_1:
|
229 |
-
# st.header("Texto Sumarizado:")
|
230 |
-
# with st.spinner("Carregando sumarização..."):
|
231 |
-
# summary = get_summarization(extractive, texto_cru, compression_rate)
|
232 |
-
# # Usando o GPT para corrigir a transcrição, caso o vídeo seja em PT-BR:
|
233 |
-
# if language == 'Português (pt)':
|
234 |
-
# summary = get_correction(summary)
|
235 |
-
# # Usando o GPT para traduzir a transcrição para PT-BR, caso o usuário prefira:
|
236 |
-
# elif language == 'Inglês (en)' and translate == 'Sim':
|
237 |
-
# with st.spinner("Traduzindo sumarização..."):
|
238 |
-
# summary = get_translation(summary)
|
239 |
-
# st.session_state['summary'] = summary
|
240 |
-
# # Preparando o AlanVideos após o envio de um link:
|
241 |
-
# with model_2:
|
242 |
-
# st.header("Resposta das perguntas:")
|
243 |
-
# with st.spinner("Preparando AlanVideoss..."):
|
244 |
-
# # Separando o texto em chunks:
|
245 |
-
# chunks = get_chunks(texto_cru)
|
246 |
-
# # Armazenando os pedaços de texto em embeddings:
|
247 |
-
# vectorstore = get_vectorstore(chunks)
|
248 |
-
# # Criando o chatbot:
|
249 |
-
# st.session_state.alanvideos = alan_videos(vectorstore)
|
250 |
-
#
|
251 |
-
# # Apresentando os resultados:
|
252 |
-
# with model:
|
253 |
-
# # Resultado do modelo de sumarização:
|
254 |
-
# with model_1:
|
255 |
-
# if 'summary' in st.session_state:
|
256 |
-
# st.write(st.session_state['summary'])
|
257 |
-
# # Resultado do AlanVideos:
|
258 |
-
# if 'summary' in st.session_state:
|
259 |
-
# if "chat_history" not in st.session_state:
|
260 |
-
# st.session_state.chat_history = [AIMessage(content=f"Olá, meu nome é Alan, e estou aqui para responder perguntas sobre o vídeo. Como posso ajudar?")]
|
261 |
-
# pergunta = st.chat_input('Faça uma pergunta sobre o vídeo: ')
|
262 |
-
# if pergunta is not None and pergunta != "":
|
263 |
-
# resposta = chat(pergunta)
|
264 |
-
# st.session_state.chat_history.append(HumanMessage(content=pergunta))
|
265 |
-
# st.session_state.chat_history.append(AIMessage(content=resposta))
|
266 |
-
# for message in st.session_state.chat_history:
|
267 |
-
# if isinstance(message, AIMessage):
|
268 |
-
# with st.chat_message("AI"):
|
269 |
-
# st.write(message.content)
|
270 |
-
# elif isinstance(message, HumanMessage):
|
271 |
-
# with st.chat_message("Human"):
|
272 |
-
# st.write(message.content)
|
273 |
-
#
|
274 |
-
# main()
|
275 |
-
|
276 |
-
!wget -q -O - ipv4.icanhazip.com
|
277 |
-
|
278 |
-
!streamlit run app.py & npx localtunnel --port 8501
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.py
ADDED
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import re
|
3 |
+
import streamlit as st
|
4 |
+
import transformers
|
5 |
+
from transformers import pipeline
|
6 |
+
from transformers import AutoTokenizer
|
7 |
+
import nltk
|
8 |
+
from PIL import Image
|
9 |
+
import torch
|
10 |
+
import ffmpeg
|
11 |
+
import speech_recognition as sr
|
12 |
+
from pytube import YouTube
|
13 |
+
import string
|
14 |
+
import whisper
|
15 |
+
from moviepy.editor import AudioFileClip
|
16 |
+
from langchain.text_splitter import CharacterTextSplitter
|
17 |
+
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
|
18 |
+
from langchain.embeddings import OpenAIEmbeddings
|
19 |
+
from langchain.vectorstores import FAISS
|
20 |
+
from langchain.chat_models import ChatOpenAI
|
21 |
+
from langchain.memory import ConversationBufferWindowMemory
|
22 |
+
from langchain.chains import ConversationalRetrievalChain
|
23 |
+
from langchain.callbacks import get_openai_callback
|
24 |
+
from key import openai_api_key
|
25 |
+
from langchain import PromptTemplate
|
26 |
+
from langchain import LLMChain
|
27 |
+
os.environ['OPENAI_API_KEY'] = openai_api_key
|
28 |
+
|
29 |
+
|
30 |
+
|
31 |
+
# Criando a função que corta o texto em chunks:
|
32 |
+
def get_chunks(texto_transcrito):
|
33 |
+
"""Função que recebe uma string (um texto transcrito) e devolve
|
34 |
+
uma lista de strings, em que cada string ("chunk") contém um
|
35 |
+
tamanho específico, com overlap entre os pedaços. """
|
36 |
+
text_splitter=CharacterTextSplitter(separator='.', chunk_size=1000, chunk_overlap=100, length_function=len)
|
37 |
+
chunks = text_splitter.split_text(texto_transcrito)
|
38 |
+
return chunks
|
39 |
+
|
40 |
+
# Criando a função de vectorstore para transformar os chunks de texto em embeddings:
|
41 |
+
def get_vectorstore(chunks):
|
42 |
+
"""Função que recebe uma lista de chunks de texto e
|
43 |
+
os converte em embeddings (representações numéricas)
|
44 |
+
usando um modelo de embeddings pré-treinado. """
|
45 |
+
embeddings = OpenAIEmbeddings()
|
46 |
+
vectorstore = FAISS.from_texts(texts=chunks, embedding=embeddings)
|
47 |
+
return vectorstore
|
48 |
+
|
49 |
+
|
50 |
+
# Criando a função para converter o vídeo para o formato adequado:
|
51 |
+
@st.cache_data
|
52 |
+
def convert_mp4_to_wav(mp4_file, wav_file):
|
53 |
+
"""Função que converte um arquivo de vídeo no formato MP4 para um arquivo de
|
54 |
+
áudio no formato WAV a partir das seguintes entradas: o caminho do arquivo
|
55 |
+
de vídeo no formato MP4 que se deseja converter; o caminho onde o arquivo
|
56 |
+
de áudio WAV resultante será salvo. Nenhuma saída explícita é retornada."""
|
57 |
+
video = AudioFileClip(mp4_file)
|
58 |
+
video.write_audiofile(wav_file)
|
59 |
+
|
60 |
+
# Criando a função que gera a transcrição:
|
61 |
+
@st.cache_data
|
62 |
+
def get_transcriptions(url):
|
63 |
+
""" Função que recebe um link de um vídeo no YouTube e
|
64 |
+
devolve um dicionário contendo o título do vídeo (key)
|
65 |
+
e a transcrição de seu áudio (value). """
|
66 |
+
dicionario = {}
|
67 |
+
# Baixando o áudio:
|
68 |
+
youtube_content = YouTube(url)
|
69 |
+
audio_streams = youtube_content.streams.filter(only_audio=True)
|
70 |
+
audio_streams[0].download()
|
71 |
+
title = youtube_content.title
|
72 |
+
# Convertendo para Wav:
|
73 |
+
mp4_file = '/content/'+''.join(char for char in title if char not in string.punctuation.replace('/', '').replace('-', '').replace('!', '').replace('(', '').replace(')', ''))+'.mp4'
|
74 |
+
wav_file = '/content/'+''.join(char for char in title if char not in string.punctuation.replace('/', '').replace('-', '').replace('!', '').replace('(', '').replace(')', ''))+'.wav'
|
75 |
+
convert_mp4_to_wav(mp4_file, wav_file)
|
76 |
+
# Inicializando o reconhecedor de fala:
|
77 |
+
r = sr.Recognizer()
|
78 |
+
# Carregando o áudio gravado pelo Whisper em um objeto de áudio:
|
79 |
+
with sr.AudioFile(wav_file) as source:
|
80 |
+
audio = r.record(source)
|
81 |
+
# Transcrevendo:
|
82 |
+
texto_transcrito = r.recognize_whisper(audio)
|
83 |
+
# Adicionando ao dicionario:
|
84 |
+
dicionario[title] = texto_transcrito
|
85 |
+
return dicionario
|
86 |
+
|
87 |
+
|
88 |
+
# Criando a função que carrega o sumarizador extrativo (para português e inglês) via HuggingFace:
|
89 |
+
@st.cache_resource
|
90 |
+
def load_extractive():
|
91 |
+
""" Função sem valores de entrada que carrega o modelo
|
92 |
+
de sumarização extrativa via HuggingFace. """
|
93 |
+
return pipeline("summarization", model="NotXia/longformer-bio-ext-summ", tokenizer=AutoTokenizer.from_pretrained("NotXia/longformer-bio-ext-summ"), trust_remote_code=True)
|
94 |
+
|
95 |
+
# Criando a função que gera a sumarização extrativa:
|
96 |
+
@st.cache_data
|
97 |
+
def get_summarization(_model_pipeline, full_text, ratio):
|
98 |
+
""" Função que recebe um texto completo a ser resumido, juntamente
|
99 |
+
à taxa desejada de sumarização e a pipeline do modelo que fará o
|
100 |
+
sumário, e devolve a versão resumida desse texto. """
|
101 |
+
sentences = nltk.sent_tokenize(full_text)
|
102 |
+
extractive_sentences = _model_pipeline({"sentences": sentences}, strategy="ratio", strategy_args=ratio)
|
103 |
+
extractive_text = " ".join(extractive_sentences[0])
|
104 |
+
return extractive_text
|
105 |
+
|
106 |
+
|
107 |
+
# Criando a função que gera a tradução do texto a partir do ChatGPT:
|
108 |
+
@st.cache_data
|
109 |
+
def get_translation(summarized_text):
|
110 |
+
""" Função que recebe um resumo a ser traduzido,
|
111 |
+
juntamente à pipeline do modelo que fará a tradução,
|
112 |
+
e devolve a versão traduzida do texto. """
|
113 |
+
LLM = ChatOpenAI(openai_api_key=openai_api_key, temperature=0.25, model_name="gpt-3.5-turbo")
|
114 |
+
messages = [SystemMessage(content='Você é um especialista em traduções de texto do inglês para português'), HumanMessage(content=summarized_text)]
|
115 |
+
translation = LLM(messages)
|
116 |
+
return translation.content
|
117 |
+
|
118 |
+
|
119 |
+
# Criando a função que corrige os erros de transcrição do texto a partir do ChatGPT:
|
120 |
+
@st.cache_data
|
121 |
+
def get_correction(transcription):
|
122 |
+
""" Função que recebe a transcrição (em PT-BR) e corrige eventuais
|
123 |
+
erros do whisper - por exemplo, a troca de palavras que, embora
|
124 |
+
semelhantes na pronúncia, são totalmente absurdas no contexto. """
|
125 |
+
correction_prompt = PromptTemplate.from_template(template = 'Você é um especialista em correção de textos. Você receberá uma transcrição de um áudio e deverá substituir as palavras transcritas erroneamente, considerando apenas a pronúncia, por palavras adequadas que façam sentido no contexto do texto. Além disso, corrija questões gramáticais para facilitar a compreensão. Corrija a seguinte transcrição: {transcription}')
|
126 |
+
LLM = ChatOpenAI(openai_api_key=openai_api_key, temperature=0.1, model_name="gpt-3.5-turbo")
|
127 |
+
corrector = LLMChain(prompt=correction_prompt, llm=LLM)
|
128 |
+
with get_openai_callback() as cb:
|
129 |
+
corrected_transcription = corrector.run({"transcription": transcription})
|
130 |
+
total_t = cb.total_tokens
|
131 |
+
prompt_t = cb.prompt_tokens
|
132 |
+
completion_t = cb.completion_tokens
|
133 |
+
total_cost = cb.total_cost
|
134 |
+
return corrected_transcription
|
135 |
+
|
136 |
+
|
137 |
+
# Criando o chatbot
|
138 |
+
def alan_videos(vectorstore):
|
139 |
+
""" Função que inicializa e configura um LLM da OpenAI
|
140 |
+
e retorna um chatbot configurado pronto para uso. """
|
141 |
+
memory = ConversationBufferWindowMemory(memory_key='chat_history', return_messages=True, k=3)
|
142 |
+
LLM = ChatOpenAI(openai_api_key=openai_api_key, temperature=0.25, model_name="gpt-3.5-turbo")
|
143 |
+
retriever=vectorstore.as_retriever()
|
144 |
+
chatbot = ConversationalRetrievalChain.from_llm(llm=LLM, retriever=retriever, memory=memory)
|
145 |
+
return chatbot
|
146 |
+
|
147 |
+
# Criando um modelo de chat:
|
148 |
+
def chat(pergunta):
|
149 |
+
""" Função que processa uma pergunta utilizando o chatbot
|
150 |
+
configurado (alan_videos) e retorna sua resposta. """
|
151 |
+
with get_openai_callback() as cb:
|
152 |
+
resposta = st.session_state.alanvideos.invoke({"question": pergunta})
|
153 |
+
total_t = cb.total_tokens
|
154 |
+
prompt_t = cb.prompt_tokens
|
155 |
+
completion_t = cb.completion_tokens
|
156 |
+
total_cost = cb.total_cost
|
157 |
+
return resposta['answer']
|
158 |
+
|
159 |
+
|
160 |
+
# Criando a função para customização com CSS:
|
161 |
+
def local_css(file_name):
|
162 |
+
""" Função que carrega um arquivo CSS local e aplica o estilo
|
163 |
+
ao Streamlit app, personalizando a interface do usuário. """
|
164 |
+
with open(file_name, "r") as f:
|
165 |
+
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
|
166 |
+
|
167 |
+
# Configurando a aba do site:
|
168 |
+
icon = Image.open("Traçado laranja #f1863d.png")
|
169 |
+
st.set_page_config(page_title="AlanVideos", page_icon=icon, layout="wide", initial_sidebar_state="auto")
|
170 |
+
|
171 |
+
|
172 |
+
|
173 |
+
# Configurando o site:
|
174 |
+
def main():
|
175 |
+
local_css("style.css")
|
176 |
+
|
177 |
+
header = st.container()
|
178 |
+
model = st.container()
|
179 |
+
model_1 = st.container()
|
180 |
+
model_2 = st.container()
|
181 |
+
|
182 |
+
# Configurando a barra lateral:
|
183 |
+
with st.sidebar:
|
184 |
+
with st.form("data_collection"):
|
185 |
+
link = st.text_area(label="Coloque o link do seu vídeo do YouTube:", height=25, placeholder="Digite seu link...")
|
186 |
+
language = st.selectbox('Qual a linguagem do seu vídeo?', ('Português (pt)', 'Inglês (en)'))
|
187 |
+
translate = st.selectbox('Você deseja que o seu vídeo seja traduzido para Português?', ('Não', 'Sim'))
|
188 |
+
compression_rate = st.slider(label="Selecione o percentual de sumarização:", min_value=0.05, max_value=0.50, value=0.25, step=0.05)
|
189 |
+
submitted = st.form_submit_button("Enviar")
|
190 |
+
|
191 |
+
# Verificando se o link do vídeo é válido:
|
192 |
+
if link != '':
|
193 |
+
if re.match((r'(https?://)?(www\.)?''(youtube|youtu|youtube-nocookie)\.(com|be)/''(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})'), link):
|
194 |
+
st.success('Dados coletados!', icon="✅")
|
195 |
+
else:
|
196 |
+
st.error('Link inválido. Por favor, insira um link do YouTube.', icon="🚨")
|
197 |
+
|
198 |
+
if "alanvideos" not in st.session_state:
|
199 |
+
st.session_state.alanvideos = None
|
200 |
+
|
201 |
+
# Configurando o cabeçalho:
|
202 |
+
with header:
|
203 |
+
st.title(":orange[Alan]Chat")
|
204 |
+
st.subheader("Olá, usuário! Este é um projeto que utiliza técnicas de inteligência artificial para simplificar e acelerar a compreensão de conteúdo audiovisual. Por favor, preencha o formulário ao lado para que possamos responder as suas dúvidas a respeito de um vídeo do YouTube! :)", divider = "orange")
|
205 |
+
|
206 |
+
# Configurando os modelos:
|
207 |
+
with model:
|
208 |
+
if submitted and re.match((r'(https?://)?(www\.)?''(youtube|youtu|youtube-nocookie)\.(com|be)/''(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})'), link):
|
209 |
+
with st.spinner("Carregando modelos..."):
|
210 |
+
nltk.download("punkt")
|
211 |
+
extractive = load_extractive()
|
212 |
+
with st.spinner("Transcrevendo texto..."):
|
213 |
+
transcription = get_transcriptions(link)
|
214 |
+
texto_cru = ''.join(list(transcription.values()))
|
215 |
+
# Preparando o modelo de sumarização após o envio de um link:
|
216 |
+
with model_1:
|
217 |
+
st.header("Texto Sumarizado:")
|
218 |
+
with st.spinner("Carregando sumarização..."):
|
219 |
+
summary = get_summarization(extractive, texto_cru, compression_rate)
|
220 |
+
# Usando o GPT para corrigir a transcrição, caso o vídeo seja em PT-BR:
|
221 |
+
if language == 'Português (pt)':
|
222 |
+
summary = get_correction(summary)
|
223 |
+
# Usando o GPT para traduzir a transcrição para PT-BR, caso o usuário prefira:
|
224 |
+
elif language == 'Inglês (en)' and translate == 'Sim':
|
225 |
+
with st.spinner("Traduzindo sumarização..."):
|
226 |
+
summary = get_translation(summary)
|
227 |
+
st.session_state['summary'] = summary
|
228 |
+
# Preparando o AlanVideos após o envio de um link:
|
229 |
+
with model_2:
|
230 |
+
st.header("Resposta das perguntas:")
|
231 |
+
with st.spinner("Preparando AlanVideoss..."):
|
232 |
+
# Separando o texto em chunks:
|
233 |
+
chunks = get_chunks(texto_cru)
|
234 |
+
# Armazenando os pedaços de texto em embeddings:
|
235 |
+
vectorstore = get_vectorstore(chunks)
|
236 |
+
# Criando o chatbot:
|
237 |
+
st.session_state.alanvideos = alan_videos(vectorstore)
|
238 |
+
|
239 |
+
# Apresentando os resultados:
|
240 |
+
with model:
|
241 |
+
# Resultado do modelo de sumarização:
|
242 |
+
with model_1:
|
243 |
+
if 'summary' in st.session_state:
|
244 |
+
st.write(st.session_state['summary'])
|
245 |
+
# Resultado do AlanVideos:
|
246 |
+
if 'summary' in st.session_state:
|
247 |
+
if "chat_history" not in st.session_state:
|
248 |
+
st.session_state.chat_history = [AIMessage(content=f"Olá, meu nome é Alan, e estou aqui para responder perguntas sobre o vídeo. Como posso ajudar?")]
|
249 |
+
pergunta = st.chat_input('Faça uma pergunta sobre o vídeo: ')
|
250 |
+
if pergunta is not None and pergunta != "":
|
251 |
+
resposta = chat(pergunta)
|
252 |
+
st.session_state.chat_history.append(HumanMessage(content=pergunta))
|
253 |
+
st.session_state.chat_history.append(AIMessage(content=resposta))
|
254 |
+
for message in st.session_state.chat_history:
|
255 |
+
if isinstance(message, AIMessage):
|
256 |
+
with st.chat_message("AI"):
|
257 |
+
st.write(message.content)
|
258 |
+
elif isinstance(message, HumanMessage):
|
259 |
+
with st.chat_message("Human"):
|
260 |
+
st.write(message.content)
|
261 |
+
|
262 |
+
main()
|