DHEIVER commited on
Commit
f0340cd
·
verified ·
1 Parent(s): 265b5f4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -14
app.py CHANGED
@@ -4,7 +4,11 @@ from langchain_community.document_loaders import PyPDFLoader
4
  from langchain.text_splitter import RecursiveCharacterTextSplitter
5
  from langchain_community.vectorstores import Chroma
6
  from langchain_community.embeddings import HuggingFaceEmbeddings
 
 
7
  import os
 
 
8
 
9
  # CSS para estilização
10
  css = '''
@@ -16,28 +20,62 @@ footer {visibility: hidden}
16
  # Inicializar o cliente de inferência
17
  client = InferenceClient("mistralai/Mistral-7B-Instruct-v0.3")
18
 
19
- # Configurar o retriever globalmente
20
- def initialize_retriever(file_objs):
21
- """Carrega documentos PDFs e cria um retriever."""
 
 
 
 
 
 
 
 
 
 
 
22
  if not file_objs:
23
  return None, "Nenhum documento carregado."
24
 
25
- # Carregar e dividir documentos
26
  documents = []
27
  for file_obj in file_objs:
28
  loader = PyPDFLoader(file_obj.name)
29
- documents.extend(loader.load())
 
 
 
 
 
30
 
31
  # Dividir em pedaços menores
32
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=2048, chunk_overlap=128)
33
  splits = text_splitter.split_documents(documents)
34
 
35
- # Criar embeddings e banco de vetores
36
  embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
37
- vectorstore = Chroma.from_documents(documents=splits, embedding=embeddings)
38
- retriever = vectorstore.as_retriever(search_kwargs={"k": 2}) # Retorna 2 documentos mais relevantes
 
 
 
 
 
39
 
40
- return retriever, "Documentos processados com sucesso!"
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
  # Formatar o prompt para RAG
43
  def format_prompt(message, history, retriever=None, system_prompt=None):
@@ -54,9 +92,8 @@ def format_prompt(message, history, retriever=None, system_prompt=None):
54
 
55
  # Adicionar contexto recuperado, se houver retriever
56
  if retriever:
57
- # Buscar documentos relevantes
58
  docs = retriever.get_relevant_documents(message)
59
- context = "\n".join([doc.page_content for doc in docs])
60
  prompt += f"[CONTEXT] {context} [/CONTEXT]"
61
 
62
  # Adicionar a mensagem do usuário
@@ -81,7 +118,7 @@ def generate(
81
  seed=42,
82
  )
83
 
84
- # Formatar o prompt com contexto RAG, se disponível
85
  formatted_prompt = format_prompt(prompt, history, retriever, system_prompt)
86
 
87
  # Gerar resposta em streaming
@@ -113,7 +150,7 @@ def create_demo():
113
  chat_interface = gr.ChatInterface(
114
  fn=generate,
115
  additional_inputs=[
116
- gr.State(value=retriever_state), # Passa o retriever como entrada adicional
117
  gr.Textbox(label="System Prompt", placeholder="Digite um prompt de sistema (opcional)", value=None)
118
  ],
119
  title="",
@@ -130,4 +167,4 @@ def create_demo():
130
 
131
  # Lançar a aplicação
132
  demo = create_demo()
133
- demo.queue().launch(share=False)
 
4
  from langchain.text_splitter import RecursiveCharacterTextSplitter
5
  from langchain_community.vectorstores import Chroma
6
  from langchain_community.embeddings import HuggingFaceEmbeddings
7
+ from langchain_community.retrievers import BM25Retriever
8
+ from langchain.retrievers import EnsembleRetriever
9
  import os
10
+ import re
11
+ from unidecode import unidecode
12
 
13
  # CSS para estilização
14
  css = '''
 
20
  # Inicializar o cliente de inferência
21
  client = InferenceClient("mistralai/Mistral-7B-Instruct-v0.3")
22
 
23
+ # Função de pré-processamento de texto
24
+ def preprocess_text(text):
25
+ """Pré-processa o texto removendo ruídos e normalizando."""
26
+ # Remover números de página (ex.: "Página 1", "Page 1 of 10")
27
+ text = re.sub(r'(Página|Page)\s+\d+(?:\s+of\s+\d+)?', '', text, flags=re.IGNORECASE)
28
+ # Remover múltiplos espaços e quebras de linha
29
+ text = re.sub(r'\s+', ' ', text).strip()
30
+ # Normalizar texto (remover acentos e converter para minúsculas)
31
+ text = unidecode(text.lower())
32
+ return text
33
+
34
+ # Configurar o retriever com pré-processamento e indexação avançada
35
+ def initialize_retriever(file_objs, persist_directory="chroma_db"):
36
+ """Carrega documentos PDFs, pré-processa e cria um retriever híbrido."""
37
  if not file_objs:
38
  return None, "Nenhum documento carregado."
39
 
40
+ # Carregar e pré-processar documentos
41
  documents = []
42
  for file_obj in file_objs:
43
  loader = PyPDFLoader(file_obj.name)
44
+ raw_docs = loader.load()
45
+ for doc in raw_docs:
46
+ doc.page_content = preprocess_text(doc.page_content)
47
+ # Adicionar metadados (exemplo: página e origem)
48
+ doc.metadata.update({"source": os.path.basename(file_obj.name)})
49
+ documents.extend(raw_docs)
50
 
51
  # Dividir em pedaços menores
52
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=2048, chunk_overlap=128)
53
  splits = text_splitter.split_documents(documents)
54
 
55
+ # Criar embeddings e banco de vetores (Chroma)
56
  embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
57
+ try:
58
+ # Tentar carregar um banco existente
59
+ vectorstore = Chroma(persist_directory=persist_directory, embedding_function=embeddings)
60
+ vectorstore.add_documents(splits) # Adicionar novos documentos
61
+ except:
62
+ # Criar um novo banco se não existir
63
+ vectorstore = Chroma.from_documents(documents=splits, embedding=embeddings, persist_directory=persist_directory)
64
 
65
+ # Configurar retriever semântico
66
+ semantic_retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
67
+
68
+ # Configurar retriever lexical (BM25)
69
+ bm25_retriever = BM25Retriever.from_documents(splits)
70
+ bm25_retriever.k = 2
71
+
72
+ # Combinar em um retriever híbrido
73
+ ensemble_retriever = EnsembleRetriever(
74
+ retrievers=[semantic_retriever, bm25_retriever],
75
+ weights=[0.6, 0.4] # Mais peso para busca semântica
76
+ )
77
+
78
+ return ensemble_retriever, "Documentos processados com sucesso!"
79
 
80
  # Formatar o prompt para RAG
81
  def format_prompt(message, history, retriever=None, system_prompt=None):
 
92
 
93
  # Adicionar contexto recuperado, se houver retriever
94
  if retriever:
 
95
  docs = retriever.get_relevant_documents(message)
96
+ context = "\n".join([f"[{doc.metadata.get('source', 'Unknown')}, Page {doc.metadata.get('page', 'N/A')}] {doc.page_content}" for doc in docs])
97
  prompt += f"[CONTEXT] {context} [/CONTEXT]"
98
 
99
  # Adicionar a mensagem do usuário
 
118
  seed=42,
119
  )
120
 
121
+ # Formatar o prompt com contexto RAG
122
  formatted_prompt = format_prompt(prompt, history, retriever, system_prompt)
123
 
124
  # Gerar resposta em streaming
 
150
  chat_interface = gr.ChatInterface(
151
  fn=generate,
152
  additional_inputs=[
153
+ gr.State(value=retriever_state),
154
  gr.Textbox(label="System Prompt", placeholder="Digite um prompt de sistema (opcional)", value=None)
155
  ],
156
  title="",
 
167
 
168
  # Lançar a aplicação
169
  demo = create_demo()
170
+ demo.queue().launch(share=False)