Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,7 +3,7 @@ import os
|
|
| 3 |
import json
|
| 4 |
import re
|
| 5 |
import gradio as gr
|
| 6 |
-
from typing import Dict, Any, List, Optional
|
| 7 |
import pickle
|
| 8 |
|
| 9 |
# --- Novas importações para o RAG ---
|
|
@@ -85,10 +85,11 @@ def scrape_text_from_url(url: str) -> str:
|
|
| 85 |
print(f"Erro ao raspar {url}: {e}")
|
| 86 |
return ""
|
| 87 |
|
| 88 |
-
def build_and_save_vector_store() -> str:
|
| 89 |
"""
|
| 90 |
Função principal do RAG: raspa o blog, cria chunks, gera embeddings e salva o vector store.
|
| 91 |
Esta é a nossa função de "treino".
|
|
|
|
| 92 |
"""
|
| 93 |
global vector_store
|
| 94 |
start_time = time.time()
|
|
@@ -106,7 +107,7 @@ def build_and_save_vector_store() -> str:
|
|
| 106 |
print(f"Textos extraídos de {len(all_texts)} novas páginas.")
|
| 107 |
|
| 108 |
if not all_texts:
|
| 109 |
-
return "Nenhum novo conteúdo encontrado para treinar."
|
| 110 |
|
| 111 |
# 3. Dividir os textos em chunks
|
| 112 |
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=150)
|
|
@@ -128,7 +129,8 @@ def build_and_save_vector_store() -> str:
|
|
| 128 |
pickle.dump(all_links, f)
|
| 129 |
|
| 130 |
end_time = time.time()
|
| 131 |
-
|
|
|
|
| 132 |
|
| 133 |
def load_vector_store():
|
| 134 |
"""Carrega o vector store do arquivo, se existir."""
|
|
@@ -141,7 +143,9 @@ def load_vector_store():
|
|
| 141 |
else:
|
| 142 |
print("Nenhum vector store encontrado. É necessário treinar o modelo.")
|
| 143 |
# Inicia o treino automaticamente se não houver um índice
|
| 144 |
-
|
|
|
|
|
|
|
| 145 |
|
| 146 |
def retrieve_context_from_blog(query: str, k: int = 3) -> str:
|
| 147 |
"""Busca no vector store por chunks de texto similares à pergunta."""
|
|
@@ -274,6 +278,7 @@ def responder_como_aldo(pergunta: str, modelo_escolhido: str = DEFAULT_MODEL) ->
|
|
| 274 |
"Responda com clareza, profundidade e tom acadêmico. Foque em explicar e não em só mostrar o resultado. "
|
| 275 |
"Responda sempre em português brasileiro. Use blocos de código formatados com ```. "
|
| 276 |
"Não responda nada se a pergunta não for sobre o universo de programação e tecnologia."
|
|
|
|
| 277 |
)
|
| 278 |
|
| 279 |
# Montar prompt do usuário, injetando o contexto do blog
|
|
@@ -366,6 +371,9 @@ with gr.Blocks(title="Dr. Aldo Henrique - API Externa", theme=gr.themes.Soft(),
|
|
| 366 |
with gr.Accordion("⚙️ Controle do Conhecimento (RAG)", open=False):
|
| 367 |
status_rag = gr.Textbox(label="Status do Retreino", interactive=False)
|
| 368 |
botao_retreinar = gr.Button("🔄 Atualizar Conhecimento do Blog", variant="stop")
|
|
|
|
|
|
|
|
|
|
| 369 |
|
| 370 |
with gr.Accordion("📚 Exemplos de Perguntas", open=False):
|
| 371 |
gr.Examples(
|
|
@@ -393,7 +401,13 @@ with gr.Blocks(title="Dr. Aldo Henrique - API Externa", theme=gr.themes.Soft(),
|
|
| 393 |
# Eventos
|
| 394 |
botao_perguntar.click(fn=responder_como_aldo, inputs=[entrada, modelo_select], outputs=saida, show_progress=True)
|
| 395 |
botao_testar.click(fn=testar_todos_modelos, outputs=status_api, show_progress=True)
|
| 396 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 397 |
|
| 398 |
# Lançar aplicação
|
| 399 |
if __name__ == "__main__":
|
|
|
|
| 3 |
import json
|
| 4 |
import re
|
| 5 |
import gradio as gr
|
| 6 |
+
from typing import Dict, Any, List, Optional, Tuple # Importando Tuple
|
| 7 |
import pickle
|
| 8 |
|
| 9 |
# --- Novas importações para o RAG ---
|
|
|
|
| 85 |
print(f"Erro ao raspar {url}: {e}")
|
| 86 |
return ""
|
| 87 |
|
| 88 |
+
def build_and_save_vector_store() -> Tuple[str, Optional[str], Optional[str]]: # Alterado o tipo de retorno para incluir os dois caminhos
|
| 89 |
"""
|
| 90 |
Função principal do RAG: raspa o blog, cria chunks, gera embeddings e salva o vector store.
|
| 91 |
Esta é a nossa função de "treino".
|
| 92 |
+
Retorna uma tupla (mensagem_status, caminho_do_arquivo_faiss_para_download, caminho_do_arquivo_urls_para_download).
|
| 93 |
"""
|
| 94 |
global vector_store
|
| 95 |
start_time = time.time()
|
|
|
|
| 107 |
print(f"Textos extraídos de {len(all_texts)} novas páginas.")
|
| 108 |
|
| 109 |
if not all_texts:
|
| 110 |
+
return "Nenhum novo conteúdo encontrado para treinar.", None, None # Retorna None para os arquivos se não houver conteúdo
|
| 111 |
|
| 112 |
# 3. Dividir os textos em chunks
|
| 113 |
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=150)
|
|
|
|
| 129 |
pickle.dump(all_links, f)
|
| 130 |
|
| 131 |
end_time = time.time()
|
| 132 |
+
message = f"✅ Retreino do RAG concluído em {end_time - start_time:.2f} segundos. {len(chunks)} chunks de texto processados."
|
| 133 |
+
return message, VECTOR_STORE_PATH, PROCESSED_URLS_PATH # Retorna a mensagem e os caminhos dos dois arquivos para download
|
| 134 |
|
| 135 |
def load_vector_store():
|
| 136 |
"""Carrega o vector store do arquivo, se existir."""
|
|
|
|
| 143 |
else:
|
| 144 |
print("Nenhum vector store encontrado. É necessário treinar o modelo.")
|
| 145 |
# Inicia o treino automaticamente se não houver um índice
|
| 146 |
+
# Modificado para ignorar o retorno dos caminhos dos arquivos ao carregar
|
| 147 |
+
message, _, _ = build_and_save_vector_store()
|
| 148 |
+
print(message) # Imprime a mensagem de status do treino inicial
|
| 149 |
|
| 150 |
def retrieve_context_from_blog(query: str, k: int = 3) -> str:
|
| 151 |
"""Busca no vector store por chunks de texto similares à pergunta."""
|
|
|
|
| 278 |
"Responda com clareza, profundidade e tom acadêmico. Foque em explicar e não em só mostrar o resultado. "
|
| 279 |
"Responda sempre em português brasileiro. Use blocos de código formatados com ```. "
|
| 280 |
"Não responda nada se a pergunta não for sobre o universo de programação e tecnologia."
|
| 281 |
+
"No código, sempre explique bem utilizando comentários, o aluno precisa aprender olhando os comentários."
|
| 282 |
)
|
| 283 |
|
| 284 |
# Montar prompt do usuário, injetando o contexto do blog
|
|
|
|
| 371 |
with gr.Accordion("⚙️ Controle do Conhecimento (RAG)", open=False):
|
| 372 |
status_rag = gr.Textbox(label="Status do Retreino", interactive=False)
|
| 373 |
botao_retreinar = gr.Button("🔄 Atualizar Conhecimento do Blog", variant="stop")
|
| 374 |
+
# Novos componentes para download
|
| 375 |
+
download_faiss_file = gr.File(label="Download do Índice FAISS", interactive=False, file_count="single", file_types=[".pkl"])
|
| 376 |
+
download_urls_file = gr.File(label="Download das URLs Processadas", interactive=False, file_count="single", file_types=[".pkl"])
|
| 377 |
|
| 378 |
with gr.Accordion("📚 Exemplos de Perguntas", open=False):
|
| 379 |
gr.Examples(
|
|
|
|
| 401 |
# Eventos
|
| 402 |
botao_perguntar.click(fn=responder_como_aldo, inputs=[entrada, modelo_select], outputs=saida, show_progress=True)
|
| 403 |
botao_testar.click(fn=testar_todos_modelos, outputs=status_api, show_progress=True)
|
| 404 |
+
# Atualiza o evento para a função build_and_save_vector_store
|
| 405 |
+
# Agora, ela retorna três valores: a mensagem de status e os caminhos dos dois arquivos
|
| 406 |
+
botao_retreinar.click(
|
| 407 |
+
fn=build_and_save_vector_store,
|
| 408 |
+
outputs=[status_rag, download_faiss_file, download_urls_file], # Saídas atualizadas
|
| 409 |
+
show_progress=True
|
| 410 |
+
)
|
| 411 |
|
| 412 |
# Lançar aplicação
|
| 413 |
if __name__ == "__main__":
|