danielspba commited on
Commit
466053c
·
verified ·
1 Parent(s): cdceefe

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -0
app.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sqlite3
3
+ import pandas as pd
4
+ from dotenv import load_dotenv
5
+ from langchain_community.document_loaders import PyPDFLoader
6
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
7
+ from langchain_community.vectorstores import FAISS
8
+ from langchain.embeddings import HuggingFaceEmbeddings
9
+ from langchain_openai import ChatOpenAI
10
+ from langchain.chains import ConversationalRetrievalChain
11
+ from langchain.memory import ConversationBufferMemory
12
+ import gradio as gr
13
+
14
+ # Carrega chave da API
15
+ load_dotenv()
16
+ os.environ["OPENAI_API_KEY"] = os.getenv("OPENROUTER_API_KEY")
17
+ os.environ["OPENAI_API_BASE"] = "https://openrouter.ai/api/v1"
18
+
19
+ # Carrega e divide o PDF
20
+ loader = PyPDFLoader("apostila_python.pdf")
21
+ docs = loader.load()
22
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
23
+ documents = text_splitter.split_documents(docs)
24
+
25
+ # Cria embeddings com modelo local (sem necessidade de API)
26
+ embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
27
+ vectordb = FAISS.from_documents(documents, embeddings)
28
+ retriever = vectordb.as_retriever()
29
+
30
+ # Cria banco de dados SQLite se não existir
31
+ conn = sqlite3.connect("historico_conversas.db")
32
+ cursor = conn.cursor()
33
+ cursor.execute('''
34
+ CREATE TABLE IF NOT EXISTS conversas (
35
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
36
+ aluno TEXT,
37
+ pergunta TEXT,
38
+ resposta TEXT,
39
+ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
40
+ )
41
+ ''')
42
+ conn.commit()
43
+ conn.close()
44
+
45
+ # LLM da OpenRouter
46
+ llm = ChatOpenAI(model="deepseek/deepseek-r1:free", temperature=0.4)
47
+
48
+ # Memória da conversa
49
+ memoria = ConversationBufferMemory(memory_key="chat_history", return_messages=True, output_key="answer")
50
+
51
+ # Cadeia com recuperação de contexto e memória
52
+ qa_chain = ConversationalRetrievalChain.from_llm(
53
+ llm=llm,
54
+ retriever=retriever,
55
+ memory=memoria,
56
+ return_source_documents=True,
57
+ output_key="answer"
58
+ )
59
+
60
+ # Função para salvar no banco
61
+ def salvar_conversa(nome, pergunta, resposta):
62
+ conn = sqlite3.connect("historico_conversas.db")
63
+ cursor = conn.cursor()
64
+ cursor.execute("INSERT INTO conversas (aluno, pergunta, resposta) VALUES (?, ?, ?)",
65
+ (nome or "Anônimo", pergunta, resposta))
66
+ conn.commit()
67
+ conn.close()
68
+
69
+ # Função para responder usando o PDF e memória
70
+ def responder(pergunta, nome):
71
+ try:
72
+ resultado = qa_chain.invoke({"question": pergunta})
73
+ resposta = resultado["answer"]
74
+ fontes = resultado.get("source_documents", [])
75
+
76
+ # Fallback se nenhuma fonte relevante for encontrada
77
+ if not fontes or all(len(doc.page_content.strip()) == 0 for doc in fontes):
78
+ resposta = llm.invoke(pergunta)
79
+
80
+ salvar_conversa(nome, pergunta, resposta)
81
+ return resposta
82
+
83
+ except Exception as e:
84
+ import traceback
85
+ return f"❌ Erro:\n{traceback.format_exc()}"
86
+
87
+ # Resetar memória
88
+ def resetar_memoria():
89
+ memoria.clear()
90
+ return "✅ Memória resetada com sucesso!"
91
+
92
+ # Exportar conversas para arquivos
93
+ def exportar_conversas():
94
+ conn = sqlite3.connect("historico_conversas.db")
95
+ df = pd.read_sql_query("SELECT * FROM conversas ORDER BY timestamp DESC", conn)
96
+ df.to_csv("conversas_exportadas.csv", index=False)
97
+ df.to_excel("conversas_exportadas.xlsx", index=False, engine="openpyxl")
98
+ conn.close()
99
+ return "✅ Arquivos 'conversas_exportadas.csv' e 'conversas_exportadas.xlsx' foram salvos!"
100
+
101
+ # Interface Gradio
102
+ with gr.Blocks() as app:
103
+ gr.Markdown("## 🤖 Tutor de Python com IA + Apostila PDF + Histórico em BD")
104
+ nome = gr.Textbox(label="Seu nome (opcional)", placeholder="Ex: João")
105
+ pergunta = gr.Textbox(label="Sua dúvida sobre Python", placeholder="Ex: Como usar listas em Python?")
106
+ resposta = gr.Textbox(label="Resposta do Assistente")
107
+
108
+ botao_enviar = gr.Button("Enviar")
109
+ botao_resetar = gr.Button("🔁 Resetar Memória")
110
+ botao_exportar = gr.Button("📤 Exportar Histórico")
111
+
112
+ botao_enviar.click(fn=responder, inputs=[pergunta, nome], outputs=resposta)
113
+ botao_resetar.click(fn=resetar_memoria, outputs=resposta)
114
+ botao_exportar.click(fn=exportar_conversas, outputs=resposta)
115
+
116
+ app.launch(share=True)