DHEIVER commited on
Commit
919807f
·
verified ·
1 Parent(s): 36fef6e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -43
app.py CHANGED
@@ -3,19 +3,16 @@ from typing import Optional, Tuple
3
  import gradio as gr
4
  from langchain_community.document_loaders import PyPDFLoader, DirectoryLoader
5
  from langchain.text_splitter import RecursiveCharacterTextSplitter
6
- from langchain_community.embeddings import HuggingFaceEmbeddings
7
- from langchain_community.vectorstores import FAISS
8
  from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
9
  import torch
10
  import tempfile
11
  import time
12
 
13
  # Configurações
14
- EMBEDDING_MODEL = "sentence-transformers/all-mpnet-base-v2"
15
  LLM_MODEL = "google/flan-t5-large"
16
  DOCS_DIR = "documents"
17
 
18
- class RAGSystem:
19
  def __init__(self):
20
  # Carrega o modelo e o tokenizador
21
  self.tokenizer = AutoTokenizer.from_pretrained(LLM_MODEL)
@@ -25,16 +22,10 @@ class RAGSystem:
25
  torch_dtype=torch.float32
26
  )
27
 
28
- # Configurações de embedding
29
- self.embeddings = HuggingFaceEmbeddings(
30
- model_name=EMBEDDING_MODEL,
31
- model_kwargs={'device': 'cpu'}
32
- )
33
-
34
  # Carrega a base de conhecimento
35
- self.base_db = self.load_base_knowledge()
36
 
37
- def load_base_knowledge(self) -> Optional[FAISS]:
38
  try:
39
  if not os.path.exists(DOCS_DIR):
40
  os.makedirs(DOCS_DIR)
@@ -60,14 +51,14 @@ class RAGSystem:
60
  )
61
  texts = text_splitter.split_documents(documents)
62
 
63
- # Cria o banco de dados de embeddings
64
- return FAISS.from_documents(texts, self.embeddings)
65
 
66
  except Exception as e:
67
  print(f"Erro ao carregar base de conhecimento: {str(e)}")
68
  return None
69
 
70
- def process_pdf(self, file_content: bytes) -> Optional[FAISS]:
71
  try:
72
  # Salva o PDF temporariamente
73
  with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file:
@@ -91,19 +82,25 @@ class RAGSystem:
91
  )
92
  texts = text_splitter.split_documents(documents)
93
 
94
- # Cria o banco de dados de embeddings
95
- db = FAISS.from_documents(texts, self.embeddings)
96
-
97
- # Combina com a base de conhecimento existente, se houver
98
- if self.base_db is not None:
99
- db.merge_from(self.base_db)
100
-
101
- return db
102
 
103
  except Exception as e:
104
  print(f"Erro ao processar PDF: {str(e)}")
105
  return None
106
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  def generate_response(self, file_obj, query: str, progress=gr.Progress()) -> Tuple[str, str, str]:
108
  """Retorna (resposta, status, tempo_decorrido)"""
109
  if not query.strip():
@@ -115,7 +112,7 @@ class RAGSystem:
115
 
116
  # Determina a fonte dos documentos
117
  has_pdf = file_obj is not None
118
- has_base = self.base_db is not None
119
  source_type = "both" if has_pdf and has_base else "pdf" if has_pdf else "base" if has_base else None
120
 
121
  if not source_type:
@@ -123,30 +120,26 @@ class RAGSystem:
123
 
124
  # Processa documento
125
  if has_pdf:
126
- db = self.process_pdf(file_obj)
127
- if db is None:
128
  return "Não foi possível processar o PDF.", "❌ Erro no processamento", "0s"
129
  else:
130
- db = self.base_db
 
 
 
131
 
132
  progress(0.4, desc="Buscando informações relevantes...")
133
 
134
- # Recupera os trechos relevantes
135
- retriever = db.as_retriever(
136
- search_kwargs={
137
- "k": 6, # Número de trechos recuperados
138
- "fetch_k": 10,
139
- "score_threshold": 0.5 # Limiar de relevância
140
- }
141
- )
142
- context_docs = retriever.get_relevant_documents(query)
143
 
144
- # Verifica se o contexto é relevante
145
- if not context_docs:
146
  return "🔍 Não foram encontradas informações suficientes nos documentos para responder esta pergunta.", "⚠️ Contexto insuficiente", f"{time.time() - start_time:.1f}s"
147
 
148
  # Prepara o contexto para o prompt
149
- context = "\n\n".join([doc.page_content for doc in context_docs])
150
 
151
  progress(0.6, desc="Gerando resposta...")
152
 
@@ -185,7 +178,7 @@ class RAGSystem:
185
  return f"Erro ao gerar resposta: {str(e)}", "❌ Erro", elapsed_time
186
 
187
  def create_demo():
188
- rag = RAGSystem()
189
 
190
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
191
  with gr.Column(elem_id="container"):
@@ -194,7 +187,7 @@ def create_demo():
194
  """
195
  # 🤖 Assistente de Documentos Inteligente
196
 
197
- Sistema de consulta avançada que responde perguntas sobre seus documentos usando RAG.
198
  """
199
  )
200
 
@@ -274,7 +267,7 @@ def create_demo():
274
  """
275
  ---
276
  ### 🔧 Informações do Sistema
277
- * Respostas geradas usando tecnologia RAG (Retrieval-Augmented Generation)
278
  * Processamento inteligente de documentos PDF
279
  * Respostas baseadas exclusivamente no conteúdo dos documentos
280
  * Suporte a múltiplos documentos e contextos
@@ -283,7 +276,7 @@ def create_demo():
283
 
284
  # Eventos
285
  submit_btn.click(
286
- fn=rag.generate_response,
287
  inputs=[file_input, query_input],
288
  outputs=[response_output, status_output, time_output],
289
  )
 
3
  import gradio as gr
4
  from langchain_community.document_loaders import PyPDFLoader, DirectoryLoader
5
  from langchain.text_splitter import RecursiveCharacterTextSplitter
 
 
6
  from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
7
  import torch
8
  import tempfile
9
  import time
10
 
11
  # Configurações
 
12
  LLM_MODEL = "google/flan-t5-large"
13
  DOCS_DIR = "documents"
14
 
15
+ class DocumentQA:
16
  def __init__(self):
17
  # Carrega o modelo e o tokenizador
18
  self.tokenizer = AutoTokenizer.from_pretrained(LLM_MODEL)
 
22
  torch_dtype=torch.float32
23
  )
24
 
 
 
 
 
 
 
25
  # Carrega a base de conhecimento
26
+ self.base_texts = self.load_base_knowledge()
27
 
28
+ def load_base_knowledge(self) -> Optional[list]:
29
  try:
30
  if not os.path.exists(DOCS_DIR):
31
  os.makedirs(DOCS_DIR)
 
51
  )
52
  texts = text_splitter.split_documents(documents)
53
 
54
+ # Extrai o texto dos trechos
55
+ return [doc.page_content for doc in texts]
56
 
57
  except Exception as e:
58
  print(f"Erro ao carregar base de conhecimento: {str(e)}")
59
  return None
60
 
61
+ def process_pdf(self, file_content: bytes) -> Optional[list]:
62
  try:
63
  # Salva o PDF temporariamente
64
  with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file:
 
82
  )
83
  texts = text_splitter.split_documents(documents)
84
 
85
+ # Extrai o texto dos trechos
86
+ return [doc.page_content for doc in texts]
 
 
 
 
 
 
87
 
88
  except Exception as e:
89
  print(f"Erro ao processar PDF: {str(e)}")
90
  return None
91
 
92
+ def find_relevant_texts(self, query: str, texts: list) -> list:
93
+ """Encontra trechos relevantes com base em palavras-chave da pergunta."""
94
+ relevant_texts = []
95
+ query_keywords = set(query.lower().split())
96
+
97
+ for text in texts:
98
+ text_keywords = set(text.lower().split())
99
+ if query_keywords.intersection(text_keywords):
100
+ relevant_texts.append(text)
101
+
102
+ return relevant_texts
103
+
104
  def generate_response(self, file_obj, query: str, progress=gr.Progress()) -> Tuple[str, str, str]:
105
  """Retorna (resposta, status, tempo_decorrido)"""
106
  if not query.strip():
 
112
 
113
  # Determina a fonte dos documentos
114
  has_pdf = file_obj is not None
115
+ has_base = self.base_texts is not None
116
  source_type = "both" if has_pdf and has_base else "pdf" if has_pdf else "base" if has_base else None
117
 
118
  if not source_type:
 
120
 
121
  # Processa documento
122
  if has_pdf:
123
+ pdf_texts = self.process_pdf(file_obj)
124
+ if pdf_texts is None:
125
  return "Não foi possível processar o PDF.", "❌ Erro no processamento", "0s"
126
  else:
127
+ pdf_texts = []
128
+
129
+ # Combina os textos
130
+ all_texts = pdf_texts + (self.base_texts if self.base_texts else [])
131
 
132
  progress(0.4, desc="Buscando informações relevantes...")
133
 
134
+ # Encontra trechos relevantes
135
+ relevant_texts = self.find_relevant_texts(query, all_texts)
 
 
 
 
 
 
 
136
 
137
+ # Verifica se trechos relevantes
138
+ if not relevant_texts:
139
  return "🔍 Não foram encontradas informações suficientes nos documentos para responder esta pergunta.", "⚠️ Contexto insuficiente", f"{time.time() - start_time:.1f}s"
140
 
141
  # Prepara o contexto para o prompt
142
+ context = "\n\n".join(relevant_texts)
143
 
144
  progress(0.6, desc="Gerando resposta...")
145
 
 
178
  return f"Erro ao gerar resposta: {str(e)}", "❌ Erro", elapsed_time
179
 
180
  def create_demo():
181
+ qa_system = DocumentQA()
182
 
183
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
184
  with gr.Column(elem_id="container"):
 
187
  """
188
  # 🤖 Assistente de Documentos Inteligente
189
 
190
+ Sistema de consulta avançada que responde perguntas sobre seus documentos.
191
  """
192
  )
193
 
 
267
  """
268
  ---
269
  ### 🔧 Informações do Sistema
270
+ * Respostas geradas usando tecnologia de processamento de linguagem natural
271
  * Processamento inteligente de documentos PDF
272
  * Respostas baseadas exclusivamente no conteúdo dos documentos
273
  * Suporte a múltiplos documentos e contextos
 
276
 
277
  # Eventos
278
  submit_btn.click(
279
+ fn=qa_system.generate_response,
280
  inputs=[file_input, query_input],
281
  outputs=[response_output, status_output, time_output],
282
  )