DHEIVER commited on
Commit
9224061
·
verified ·
1 Parent(s): b1996b3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -18
app.py CHANGED
@@ -1,7 +1,7 @@
1
  import os
2
  from typing import Optional
3
  import gradio as gr
4
- from langchain_community.document_loaders import PyPDFLoader
5
  from langchain.text_splitter import RecursiveCharacterTextSplitter
6
  from langchain_community.embeddings import HuggingFaceEmbeddings
7
  from langchain_community.vectorstores import FAISS
@@ -14,6 +14,7 @@ import tempfile
14
  # Configurações
15
  EMBEDDING_MODEL = "sentence-transformers/all-mpnet-base-v2"
16
  LLM_MODEL = "mistralai/Mistral-7B-v0.1"
 
17
 
18
  class RAGSystem:
19
  def __init__(self):
@@ -23,7 +24,7 @@ class RAGSystem:
23
  LLM_MODEL,
24
  torch_dtype=torch.float16,
25
  device_map="auto",
26
- load_in_8bit=True # Usa quantização 8-bit para reduzir uso de memória
27
  )
28
 
29
  # Configura o pipeline
@@ -46,8 +47,49 @@ class RAGSystem:
46
  model_kwargs={'device': 'cpu'}
47
  )
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  def process_pdf(self, file_content: bytes) -> Optional[FAISS]:
50
- """Processa o PDF e cria a base de conhecimento"""
51
  try:
52
  # Cria arquivo temporário
53
  with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file:
@@ -75,6 +117,11 @@ class RAGSystem:
75
 
76
  # Cria base de conhecimento
77
  db = FAISS.from_documents(texts, self.embeddings)
 
 
 
 
 
78
  return db
79
 
80
  except Exception as e:
@@ -83,17 +130,20 @@ class RAGSystem:
83
 
84
  def generate_response(self, file_obj, query: str) -> str:
85
  """Gera resposta para a consulta"""
86
- if file_obj is None:
87
- return "Por favor, faça upload de um arquivo PDF."
88
-
89
  if not query.strip():
90
  return "Por favor, insira uma pergunta."
91
 
92
  try:
93
- # Processa o PDF
94
- db = self.process_pdf(file_obj)
95
- if db is None:
96
- return "Não foi possível processar o PDF."
 
 
 
 
 
 
97
 
98
  # Configura o chain RAG
99
  qa_chain = RetrievalQA.from_chain_type(
@@ -108,8 +158,16 @@ class RAGSystem:
108
  return_source_documents=True
109
  )
110
 
 
 
 
 
 
 
 
 
111
  # Gera resposta
112
- result = qa_chain({"query": query})
113
  return result["result"]
114
 
115
  except Exception as e:
@@ -120,18 +178,18 @@ def create_demo():
120
  rag = RAGSystem()
121
 
122
  with gr.Blocks() as demo:
123
- gr.Markdown("# 📚 Sistema RAG com Mistral-7B")
124
- gr.Markdown("""
125
  ### Instruções:
126
- 1. Faça upload de um arquivo PDF
127
- 2. Digite sua pergunta sobre o conteúdo
128
- 3. Aguarde a resposta gerada pelo modelo
129
  """)
130
 
131
  with gr.Row():
132
  with gr.Column(scale=1):
133
  file_input = gr.File(
134
- label="Upload do PDF",
135
  type="binary",
136
  file_types=[".pdf"]
137
  )
@@ -156,7 +214,7 @@ def create_demo():
156
 
157
  gr.Examples(
158
  examples=[
159
- [None, "Qual é o tema principal deste documento?"],
160
  [None, "Pode fazer um resumo dos pontos principais?"],
161
  [None, "Quais são as principais conclusões?"]
162
  ],
 
1
  import os
2
  from typing import Optional
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
 
14
  # Configurações
15
  EMBEDDING_MODEL = "sentence-transformers/all-mpnet-base-v2"
16
  LLM_MODEL = "mistralai/Mistral-7B-v0.1"
17
+ DOCS_DIR = "documents" # Pasta com os documentos base
18
 
19
  class RAGSystem:
20
  def __init__(self):
 
24
  LLM_MODEL,
25
  torch_dtype=torch.float16,
26
  device_map="auto",
27
+ load_in_8bit=True
28
  )
29
 
30
  # Configura o pipeline
 
47
  model_kwargs={'device': 'cpu'}
48
  )
49
 
50
+ # Carrega a base de conhecimento permanente
51
+ self.base_db = self.load_base_knowledge()
52
+
53
+ def load_base_knowledge(self) -> Optional[FAISS]:
54
+ """Carrega a base de conhecimento permanente da pasta de documentos"""
55
+ try:
56
+ if not os.path.exists(DOCS_DIR):
57
+ print(f"Pasta {DOCS_DIR} não encontrada. Criando...")
58
+ os.makedirs(DOCS_DIR)
59
+ return None
60
+
61
+ # Carrega todos os PDFs da pasta
62
+ loader = DirectoryLoader(
63
+ DOCS_DIR,
64
+ glob="**/*.pdf",
65
+ loader_cls=PyPDFLoader
66
+ )
67
+ documents = loader.load()
68
+
69
+ if not documents:
70
+ print("Nenhum documento encontrado na pasta base.")
71
+ return None
72
+
73
+ # Divide o texto em chunks
74
+ text_splitter = RecursiveCharacterTextSplitter(
75
+ chunk_size=1000,
76
+ chunk_overlap=200,
77
+ length_function=len,
78
+ separators=["\n\n", "\n", ".", " ", ""]
79
+ )
80
+ texts = text_splitter.split_documents(documents)
81
+
82
+ # Cria base de conhecimento
83
+ print(f"Criando base de conhecimento com {len(texts)} chunks...")
84
+ db = FAISS.from_documents(texts, self.embeddings)
85
+ return db
86
+
87
+ except Exception as e:
88
+ print(f"Erro ao carregar base de conhecimento: {str(e)}")
89
+ return None
90
+
91
  def process_pdf(self, file_content: bytes) -> Optional[FAISS]:
92
+ """Processa o PDF do usuário"""
93
  try:
94
  # Cria arquivo temporário
95
  with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file:
 
117
 
118
  # Cria base de conhecimento
119
  db = FAISS.from_documents(texts, self.embeddings)
120
+
121
+ # Se existir uma base permanente, mescla com ela
122
+ if self.base_db is not None:
123
+ db.merge_from(self.base_db)
124
+
125
  return db
126
 
127
  except Exception as e:
 
130
 
131
  def generate_response(self, file_obj, query: str) -> str:
132
  """Gera resposta para a consulta"""
 
 
 
133
  if not query.strip():
134
  return "Por favor, insira uma pergunta."
135
 
136
  try:
137
+ # Se tiver arquivo do usuário, processa e mescla com a base
138
+ if file_obj is not None:
139
+ db = self.process_pdf(file_obj)
140
+ if db is None:
141
+ return "Não foi possível processar o PDF."
142
+ # Se não tiver arquivo do usuário, usa só a base permanente
143
+ elif self.base_db is not None:
144
+ db = self.base_db
145
+ else:
146
+ return "Nenhuma base de conhecimento disponível. Por favor, faça upload de um PDF ou adicione documentos à pasta base."
147
 
148
  # Configura o chain RAG
149
  qa_chain = RetrievalQA.from_chain_type(
 
158
  return_source_documents=True
159
  )
160
 
161
+ # Adiciona contexto sobre a fonte da resposta
162
+ prompt = f"""Com base nos documentos fornecidos, responda à seguinte pergunta:
163
+ {query}
164
+
165
+ Se a resposta vier da base de documentos permanente, indique isso no início da resposta.
166
+ Se a resposta vier do PDF enviado pelo usuário, indique isso no início da resposta.
167
+ Se não encontrar informações suficientes, indique isso claramente."""
168
+
169
  # Gera resposta
170
+ result = qa_chain({"query": prompt})
171
  return result["result"]
172
 
173
  except Exception as e:
 
178
  rag = RAGSystem()
179
 
180
  with gr.Blocks() as demo:
181
+ gr.Markdown("# 📚 Sistema RAG com Base de Conhecimento")
182
+ gr.Markdown(f"""
183
  ### Instruções:
184
+ 1. Os documentos da pasta `{DOCS_DIR}` são usados como base de conhecimento permanente
185
+ 2. Você pode fazer upload de PDFs adicionais para consulta
186
+ 3. As respostas serão baseadas em ambas as fontes quando disponíveis
187
  """)
188
 
189
  with gr.Row():
190
  with gr.Column(scale=1):
191
  file_input = gr.File(
192
+ label="Upload do PDF (opcional)",
193
  type="binary",
194
  file_types=[".pdf"]
195
  )
 
214
 
215
  gr.Examples(
216
  examples=[
217
+ [None, "Qual é o tema principal dos documentos?"],
218
  [None, "Pode fazer um resumo dos pontos principais?"],
219
  [None, "Quais são as principais conclusões?"]
220
  ],