Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -5,6 +5,7 @@ from sentence_transformers import SentenceTransformer, util
|
|
5 |
from transformers import AutoTokenizer, AutoModelForCausalLM
|
6 |
from pypdf import PdfReader
|
7 |
import os
|
|
|
8 |
|
9 |
# --- 1. Carregamento dos Modelos ---
|
10 |
# Modelo de recuperação não muda, ele é excelente para essa tarefa.
|
@@ -24,7 +25,7 @@ generator_model = AutoModelForCausalLM.from_pretrained(
|
|
24 |
)
|
25 |
print("Modelos carregados com sucesso!")
|
26 |
|
27 |
-
# --- 2. Função para Processar Arquivos Enviados (
|
28 |
def process_files(files):
|
29 |
if not files:
|
30 |
return None, "Por favor, envie um ou mais arquivos."
|
@@ -37,30 +38,53 @@ def process_files(files):
|
|
37 |
for page in reader.pages:
|
38 |
page_text = page.extract_text()
|
39 |
if page_text:
|
40 |
-
|
|
|
41 |
except Exception as e:
|
42 |
return None, f"Erro ao ler o arquivo PDF {os.path.basename(file_path)}: {e}"
|
43 |
elif file_path.endswith(".txt"):
|
44 |
try:
|
45 |
with open(file_path, 'r', encoding='utf-8') as f:
|
46 |
-
knowledge_text += f.read() + "\n"
|
47 |
except Exception as e:
|
48 |
return None, f"Erro ao ler o arquivo TXT {os.path.basename(file_path)}: {e}"
|
49 |
|
50 |
if not knowledge_text.strip():
|
51 |
return None, "Não foi possível extrair texto dos arquivos fornecidos."
|
52 |
|
53 |
-
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
return None, "O texto extraído não continha blocos de texto válidos para processamento."
|
56 |
|
57 |
-
print(f"Processando {len(
|
58 |
-
knowledge_base_embeddings = retriever_model.encode(
|
59 |
print("Base de conhecimento criada a partir dos arquivos.")
|
60 |
|
61 |
-
return (
|
|
|
62 |
|
63 |
-
# --- 3. A Função Principal do RAG (
|
64 |
def answer_question(question, knowledge_state):
|
65 |
if not question:
|
66 |
return "Por favor, insira uma pergunta."
|
@@ -84,7 +108,7 @@ def answer_question(question, knowledge_state):
|
|
84 |
print(f"Pergunta: {question}")
|
85 |
print(f"Contexto Recuperado (Top {top_k}):\n{retrieved_context}")
|
86 |
|
87 |
-
#
|
88 |
prompt = f"""### Instruction:
|
89 |
Você é um assistente de IA especialista em extrair informações de documentos técnicos. Analise o 'Contexto' para responder à 'Pergunta' seguindo estas regras rigorosamente:
|
90 |
|
@@ -127,7 +151,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as interface:
|
|
127 |
knowledge_state = gr.State()
|
128 |
gr.Markdown(
|
129 |
"""
|
130 |
-
# 🤖 RAG - Auditor de Documentos (
|
131 |
**1. Carregue seus arquivos**: Envie um ou mais certificados ou documentos nos formatos `.pdf` ou `.txt`.
|
132 |
**2. Processe os arquivos**: Clique no botão para criar a base de conhecimento.
|
133 |
**3. Faça perguntas**: Após o processamento, faça perguntas sobre o conteúdo dos documentos.
|
|
|
5 |
from transformers import AutoTokenizer, AutoModelForCausalLM
|
6 |
from pypdf import PdfReader
|
7 |
import os
|
8 |
+
import re # MÓDULO ADICIONADO para Expressões Regulares
|
9 |
|
10 |
# --- 1. Carregamento dos Modelos ---
|
11 |
# Modelo de recuperação não muda, ele é excelente para essa tarefa.
|
|
|
25 |
)
|
26 |
print("Modelos carregados com sucesso!")
|
27 |
|
28 |
+
# --- 2. Função para Processar Arquivos Enviados (COM CHUNKING ESTRUTURADO) ---
|
29 |
def process_files(files):
|
30 |
if not files:
|
31 |
return None, "Por favor, envie um ou mais arquivos."
|
|
|
38 |
for page in reader.pages:
|
39 |
page_text = page.extract_text()
|
40 |
if page_text:
|
41 |
+
# Adiciona um espaço extra entre as páginas para garantir a separação
|
42 |
+
knowledge_text += page_text + "\n\n"
|
43 |
except Exception as e:
|
44 |
return None, f"Erro ao ler o arquivo PDF {os.path.basename(file_path)}: {e}"
|
45 |
elif file_path.endswith(".txt"):
|
46 |
try:
|
47 |
with open(file_path, 'r', encoding='utf-8') as f:
|
48 |
+
knowledge_text += f.read() + "\n\n"
|
49 |
except Exception as e:
|
50 |
return None, f"Erro ao ler o arquivo TXT {os.path.basename(file_path)}: {e}"
|
51 |
|
52 |
if not knowledge_text.strip():
|
53 |
return None, "Não foi possível extrair texto dos arquivos fornecidos."
|
54 |
|
55 |
+
# MUDANÇA PRINCIPAL: Extrator Estruturado usando Regex
|
56 |
+
# Este padrão de regex divide o texto ANTES de uma linha que parece um cabeçalho de seção
|
57 |
+
# (Ex: "1. CLIENTE", "8. PADRÕES"). Isso mantém a seção inteira em um único chunk.
|
58 |
+
# O `(?m)` ativa o modo multiline, fazendo `^` corresponder ao início de cada linha.
|
59 |
+
chunk_pattern = r"(?m)(^\d+\..*)"
|
60 |
+
|
61 |
+
# Divide o texto em chunks usando o padrão e remove os vazios
|
62 |
+
text_chunks = [chunk.strip() for chunk in re.split(chunk_pattern, knowledge_text) if chunk.strip()]
|
63 |
+
|
64 |
+
# Reagrupa o cabeçalho com seu conteúdo
|
65 |
+
structured_chunks = []
|
66 |
+
i = 0
|
67 |
+
while i < len(text_chunks):
|
68 |
+
if re.match(chunk_pattern, text_chunks[i]) and i + 1 < len(text_chunks):
|
69 |
+
# Junta o cabeçalho (ex: "1. CLIENTE") com o conteúdo seguinte
|
70 |
+
structured_chunks.append(text_chunks[i] + "\n" + text_chunks[i+1])
|
71 |
+
i += 2
|
72 |
+
else:
|
73 |
+
# Adiciona conteúdo que não corresponde a um cabeçalho
|
74 |
+
structured_chunks.append(text_chunks[i])
|
75 |
+
i += 1
|
76 |
+
|
77 |
+
if not structured_chunks:
|
78 |
return None, "O texto extraído não continha blocos de texto válidos para processamento."
|
79 |
|
80 |
+
print(f"Processando {len(structured_chunks)} chunks estruturados dos arquivos...")
|
81 |
+
knowledge_base_embeddings = retriever_model.encode(structured_chunks, convert_to_tensor=True, show_progress_bar=True)
|
82 |
print("Base de conhecimento criada a partir dos arquivos.")
|
83 |
|
84 |
+
return (structured_chunks, knowledge_base_embeddings), f"✅ Sucesso! {len(files)} arquivo(s) processado(s), gerando {len(structured_chunks)} chunks estruturados."
|
85 |
+
|
86 |
|
87 |
+
# --- 3. A Função Principal do RAG (sem alterações) ---
|
88 |
def answer_question(question, knowledge_state):
|
89 |
if not question:
|
90 |
return "Por favor, insira uma pergunta."
|
|
|
108 |
print(f"Pergunta: {question}")
|
109 |
print(f"Contexto Recuperado (Top {top_k}):\n{retrieved_context}")
|
110 |
|
111 |
+
# Prompt com regras explícitas de extração de entidades
|
112 |
prompt = f"""### Instruction:
|
113 |
Você é um assistente de IA especialista em extrair informações de documentos técnicos. Analise o 'Contexto' para responder à 'Pergunta' seguindo estas regras rigorosamente:
|
114 |
|
|
|
151 |
knowledge_state = gr.State()
|
152 |
gr.Markdown(
|
153 |
"""
|
154 |
+
# 🤖 RAG - Auditor de Documentos (v9 - Chunking Estruturado)
|
155 |
**1. Carregue seus arquivos**: Envie um ou mais certificados ou documentos nos formatos `.pdf` ou `.txt`.
|
156 |
**2. Processe os arquivos**: Clique no botão para criar a base de conhecimento.
|
157 |
**3. Faça perguntas**: Após o processamento, faça perguntas sobre o conteúdo dos documentos.
|