Spaces:
Sleeping
Sleeping
| import os | |
| import sqlite3 | |
| import pandas as pd | |
| from dotenv import load_dotenv | |
| from langchain_community.document_loaders import PyPDFLoader | |
| from langchain.text_splitter import RecursiveCharacterTextSplitter | |
| from langchain_community.vectorstores import FAISS | |
| from langchain.embeddings import HuggingFaceEmbeddings | |
| from langchain_openai import ChatOpenAI | |
| from langchain.chains import ConversationalRetrievalChain | |
| from langchain.memory import ConversationBufferMemory | |
| import gradio as gr | |
| # Carrega chave da API | |
| load_dotenv() | |
| os.environ["OPENAI_API_KEY"] = os.getenv("OPENROUTER_API_KEY") | |
| os.environ["OPENAI_API_BASE"] = "https://openrouter.ai/api/v1" | |
| # Carrega e divide o PDF | |
| loader = PyPDFLoader("apostila_python.pdf") | |
| docs = loader.load() | |
| text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100) | |
| documents = text_splitter.split_documents(docs) | |
| # Cria embeddings com modelo local (sem necessidade de API) | |
| embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2") | |
| vectordb = FAISS.from_documents(documents, embeddings) | |
| retriever = vectordb.as_retriever() | |
| # Cria banco de dados SQLite se não existir | |
| conn = sqlite3.connect("historico_conversas.db") | |
| cursor = conn.cursor() | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS conversas ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| aluno TEXT, | |
| pergunta TEXT, | |
| resposta TEXT, | |
| timestamp DATETIME DEFAULT CURRENT_TIMESTAMP | |
| ) | |
| ''') | |
| conn.commit() | |
| conn.close() | |
| # LLM da OpenRouter | |
| llm = ChatOpenAI(model="deepseek/deepseek-r1:free", temperature=0.4) | |
| # Memória da conversa | |
| memoria = ConversationBufferMemory(memory_key="chat_history", return_messages=True, output_key="answer") | |
| # Cadeia com recuperação de contexto e memória | |
| qa_chain = ConversationalRetrievalChain.from_llm( | |
| llm=llm, | |
| retriever=retriever, | |
| memory=memoria, | |
| return_source_documents=True, | |
| output_key="answer" | |
| ) | |
| # Função para salvar no banco | |
| def salvar_conversa(nome, pergunta, resposta): | |
| conn = sqlite3.connect("historico_conversas.db") | |
| cursor = conn.cursor() | |
| cursor.execute("INSERT INTO conversas (aluno, pergunta, resposta) VALUES (?, ?, ?)", | |
| (nome or "Anônimo", pergunta, resposta)) | |
| conn.commit() | |
| conn.close() | |
| # Função para responder usando o PDF e memória | |
| def responder(pergunta, nome): | |
| try: | |
| resultado = qa_chain.invoke({"question": pergunta}) | |
| resposta = resultado["answer"] | |
| fontes = resultado.get("source_documents", []) | |
| # Fallback se nenhuma fonte relevante for encontrada | |
| if not fontes or all(len(doc.page_content.strip()) == 0 for doc in fontes): | |
| resposta = llm.invoke(pergunta) | |
| salvar_conversa(nome, pergunta, resposta) | |
| return resposta | |
| except Exception as e: | |
| import traceback | |
| return f"❌ Erro:\n{traceback.format_exc()}" | |
| # Resetar memória | |
| def resetar_memoria(): | |
| memoria.clear() | |
| return "✅ Memória resetada com sucesso!" | |
| # Exportar conversas para arquivos | |
| def exportar_conversas(): | |
| conn = sqlite3.connect("historico_conversas.db") | |
| df = pd.read_sql_query("SELECT * FROM conversas ORDER BY timestamp DESC", conn) | |
| df.to_csv("conversas_exportadas.csv", index=False) | |
| df.to_excel("conversas_exportadas.xlsx", index=False, engine="openpyxl") | |
| conn.close() | |
| return "✅ Arquivos 'conversas_exportadas.csv' e 'conversas_exportadas.xlsx' foram salvos!" | |
| # Interface Gradio | |
| with gr.Blocks() as app: | |
| gr.Markdown("## 🤖 Tutor de Python com IA + Apostila PDF + Histórico em BD") | |
| nome = gr.Textbox(label="Seu nome (opcional)", placeholder="Ex: João") | |
| pergunta = gr.Textbox(label="Sua dúvida sobre Python", placeholder="Ex: Como usar listas em Python?") | |
| resposta = gr.Textbox(label="Resposta do Assistente") | |
| botao_enviar = gr.Button("Enviar") | |
| botao_resetar = gr.Button("🔁 Resetar Memória") | |
| botao_exportar = gr.Button("📤 Exportar Histórico") | |
| botao_enviar.click(fn=responder, inputs=[pergunta, nome], outputs=resposta) | |
| botao_resetar.click(fn=resetar_memoria, outputs=resposta) | |
| botao_exportar.click(fn=exportar_conversas, outputs=resposta) | |
| app.launch(share=True) |