AgentPDF / interface /modern_interface.py
rwayz's picture
Update interface/modern_interface.py
f9ef443 verified
"""
Interface Gradio moderna para o AgentPDF com tema escuro.
Esta interface replica o design moderno da imagem fornecida.
"""
import os
import shutil
import gradio as gr
from typing import List, Tuple, Optional
from main_graph import get_agent_graph, process_pdf_file, ask_pdf_question
from utils.config import Config
from utils.logger import main_logger
class ModernAgentPDFInterface:
"""Interface moderna para o AgentPDF."""
def __init__(self):
"""Inicializa a interface."""
self.current_state = None
self.chat_history = []
self.pdf_processed = False
self.current_pdf_name = None
def upload_pdf(self, file) -> Tuple[str, str, List[List[str]]]:
"""Processa o upload de um arquivo PDF."""
try:
if file is None:
return "❌ Erro: Nenhum arquivo selecionado", "Selecione um arquivo PDF", []
if not file.name.lower().endswith('.pdf'):
return "❌ Erro: Formato inválido", "Apenas arquivos PDF são aceitos", []
# Processa o arquivo
upload_dir = Config.UPLOAD_DIR
os.makedirs(upload_dir, exist_ok=True)
filename = f"uploaded_{os.path.basename(file.name)}"
pdf_path = os.path.join(upload_dir, filename)
shutil.copy2(file.name, pdf_path)
# Processa o PDF
result = process_pdf_file(pdf_path)
if result["success"]:
self.current_state = result["result"]
self.pdf_processed = True
self.current_pdf_name = os.path.basename(file.name)
self.chat_history = []
welcome_message = [
["Sistema", f"✅ PDF '{self.current_pdf_name}' processado com sucesso!"]
]
return (
"✅ Documento processado",
f"PDF: {self.current_pdf_name}\nStatus: Pronto para perguntas",
welcome_message
)
else:
self.pdf_processed = False
return "❌ Erro no processamento", f"Erro: {result['error']}", []
except Exception as e:
main_logger.error(f"Erro no upload: {e}")
return "❌ Erro inesperado", f"Erro: {str(e)}", []
def chat_with_pdf(self, message: str, history: List[List[str]]) -> Tuple[List[List[str]], str]:
"""Processa uma mensagem do chat."""
try:
if not self.pdf_processed or not self.current_state:
error_msg = "❌ Faça upload de um PDF primeiro"
history.append([message, error_msg])
return history, ""
if not message.strip():
return history, ""
# Processa a pergunta
result = ask_pdf_question(message, self.current_state)
if result["success"]:
answer = result["answer"]
if result.get("result"):
self.current_state = result["result"]
else:
answer = f"❌ Erro: {result['error']}"
history.append([message, answer])
return history, ""
except Exception as e:
main_logger.error(f"Erro no chat: {e}")
error_msg = f"❌ Erro inesperado: {str(e)}"
history.append([message, error_msg])
return history, ""
def clear_chat(self) -> Tuple[List, str]:
"""Limpa o histórico do chat."""
self.chat_history = []
return [], ""
def get_pdf_info(self) -> str:
"""Retorna informações sobre o PDF atual."""
if not self.pdf_processed or not self.current_pdf_name:
return "Nenhum documento carregado"
info = f"📄 {self.current_pdf_name}\n"
info += f"✅ Processado e indexado\n"
if self.current_state:
chunks = self.current_state.get("pdf_chunks", [])
if chunks:
info += f"📊 {len(chunks)} seções"
return info
def create_interface(self) -> gr.Blocks:
"""Cria a interface moderna usando templates nativos do Gradio."""
# CSS simples e limpo
css = """
.chat-container {
height: 70vh !important;
}
.send-button {
height: 56px !important;
min-height: 56px !important;
}
.sidebar-config {
max-width: 320px !important;
min-width: 320px !important;
width: 320px !important;
}
"""
with gr.Blocks(
title="AgentPDF",
theme=gr.themes.Soft(
primary_hue="blue",
secondary_hue="slate",
neutral_hue="slate"
),
css=css
) as interface:
with gr.Row():
# SIDEBAR - Configurações
with gr.Column(scale=1, elem_classes=["sidebar-config"]):
gr.Markdown("## ⚙️ Configurações")
with gr.Group():
file_upload = gr.File(
label="Selecione um PDF",
file_types=[".pdf"],
type="filepath"
)
upload_btn = gr.Button(
"🚀 Processar PDF",
variant="primary",
size="lg"
)
with gr.Group():
upload_status = gr.Textbox(
label="📊 Status",
interactive=False,
placeholder="Aguardando upload...",
lines=1
)
pdf_info = gr.Textbox(
label="📄 Informações",
interactive=False,
value="Nenhum documento carregado",
lines=2
)
# ÁREA PRINCIPAL - Chat
with gr.Column(scale=3):
gr.Markdown("## 💬 Conversa")
chatbot = gr.Chatbot(
elem_classes=["chat-container"],
show_copy_button=True,
bubble_full_width=False
)
with gr.Row():
msg_input = gr.Textbox(
placeholder="Digite sua pergunta sobre o PDF...",
show_label=False,
scale=5,
lines=1
)
send_btn = gr.Button(
"📤",
variant="primary",
scale=1,
elem_classes=["send-button"]
)
# Eventos da interface
upload_btn.click(
fn=self.upload_pdf,
inputs=[file_upload],
outputs=[upload_status, pdf_info, chatbot],
show_progress=True
)
send_btn.click(
fn=self.chat_with_pdf,
inputs=[msg_input, chatbot],
outputs=[chatbot, msg_input],
show_progress=True
)
msg_input.submit(
fn=self.chat_with_pdf,
inputs=[msg_input, chatbot],
outputs=[chatbot, msg_input],
show_progress=True
)
return interface
def create_modern_gradio_app() -> gr.Blocks:
"""Cria a aplicação Gradio moderna."""
interface = ModernAgentPDFInterface()
return interface.create_interface()
if __name__ == "__main__":
app = create_modern_gradio_app()
app.launch(
server_name="0.0.0.0",
server_port=Config.GRADIO_PORT,
share=Config.GRADIO_SHARE,
show_error=True
)