Files changed (1) hide show
  1. app.py → train.py +41 -47
app.py → train.py RENAMED
@@ -1,42 +1,29 @@
1
- # --- 1. IMPORTS ---
2
- # Imports do seu train.py e do Gradio
3
  import os
4
  import glob
5
  import json
6
  import csv
7
  import numpy as np
 
8
  from sentence_transformers import SentenceTransformer
9
  import zipfile
10
  import xml.etree.ElementTree as ET
11
- import gradio as gr
12
- import shutil
13
 
14
- # --- 2. CONFIGURAÇÕES E CONSTANTES ---
15
- # Caminhos relativos são melhores para portabilidade no Hugging Face Spaces
16
- DATA_DIR = "dados"
17
- EXTRACT_DIR = os.path.join(DATA_DIR, "dados_extraidos")
18
-
19
- # ATIVA O ARMAZENAMENTO PERSISTENTE NAS CONFIGURAÇÕES DO SEU SPACE!
20
- # Se ativado, mude o caminho para algo como "/data/meus_embeddings.npy"
21
- OUTPUT_FILENAME = "meus_embeddings_e5_large.npy"
22
-
23
- # --- 3. SUAS FUNÇÕES DE PROCESSAMENTO (DO TRAIN.PY) ---
24
- # Copiamos suas funções de ajuda diretamente para cá.
25
 
26
  def setup_data():
27
- """Descompacta os arquivos .zip e retorna o diretório de processamento."""
28
  os.makedirs(EXTRACT_DIR, exist_ok=True)
29
- zip_files = glob.glob(os.path.join(DATA_DIR, "*.zip")) # Simplificado para buscar zips na pasta 'dados'
30
  if not zip_files:
31
  print("Nenhum arquivo .zip encontrado, usando o diretório de dados principal.")
32
  return DATA_DIR
33
  for zip_path in zip_files:
 
34
  with zipfile.ZipFile(zip_path, 'r') as zf:
35
  zf.extractall(EXTRACT_DIR)
36
  return EXTRACT_DIR
37
 
38
  def xml_to_dict(element):
39
- """Converte um elemento XML para um dicionário Python."""
40
  d = {}
41
  for child in element:
42
  child_dict = xml_to_dict(child)
@@ -51,7 +38,6 @@ def xml_to_dict(element):
51
  return d
52
 
53
  def serialize_item_to_text(item_dict):
54
- """Converte um dicionário (de JSON, CSV, etc.) para uma string de texto plano."""
55
  parts = []
56
  if not isinstance(item_dict, dict):
57
  return str(item_dict)
@@ -66,30 +52,21 @@ def serialize_item_to_text(item_dict):
66
  parts.append(f"{key}: {value}")
67
  return ", ".join(parts)
68
 
69
- # --- 4. FUNÇÃO ORQUESTRADORA (LÓGICA PRINCIPAL) ---
70
- # Esta função substitui a sua função `main()` e é chamada pelo Gradio.
71
- # Ela usa `yield` para enviar atualizações de progresso para a interface.
72
-
73
- def run_full_process():
74
- """Executa o pipeline completo e envia o progresso para a UI."""
75
-
76
- # --- ETAPA 1: SETUP E PROCESSAMENTO DE ARQUIVOS ---
77
- yield "Iniciando... Descompactando arquivos..."
78
  process_dir = setup_data()
79
-
80
  csv.field_size_limit(10_000_000)
81
- all_files = glob.glob(os.path.join(process_dir, "**/*.json"), recursive=True) + \
82
- glob.glob(os.path.join(process_dir, "**/*.csv"), recursive=True) + \
83
- glob.glob(os.path.join(process_dir, "**/*.xml"), recursive=True)
84
-
85
- yield f"🔎 Encontrados {len(all_files)} arquivos para processar."
 
 
 
86
 
87
  documents = []
88
- for idx, filepath in enumerate(all_files):
89
  try:
90
- # Mostra o progresso na interface em vez de usar tqdm
91
- yield f"Processando arquivo {idx + 1}/{len(all_files)}: {os.path.basename(filepath)}"
92
-
93
  if filepath.endswith('.json'):
94
  with open(filepath, 'r', encoding='utf-8') as f:
95
  data = json.load(f)
@@ -107,17 +84,34 @@ def run_full_process():
107
  xml_dict = {root.tag: xml_to_dict(root)}
108
  documents.append(serialize_item_to_text(xml_dict))
109
  except Exception as e:
110
- yield f"⚠️ Erro ao processar {os.path.basename(filepath)}: {e}"
111
 
112
- yield f"Processamento de arquivos concluído! {len(documents)} documentos criados."
113
  if not documents:
114
- yield "Nenhum documento encontrado para gerar embeddings. Processo encerrado."
115
  return
116
 
117
- # --- ETAPA 2: GERAÇÃO DE EMBEDDINGS ---
118
- yield "Carregando modelo de alta performance: intfloat/multilingual-e5-large..."
 
 
 
 
 
 
 
 
119
 
120
- # Use um cache dentro do seu Space para não baixar o modelo toda vez
121
- cache_path = './model_cache'
122
- os.makedirs(cache_path, exist_ok=True)
123
- model = SentenceTransformer('intfloat/multilingual-
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import glob
3
  import json
4
  import csv
5
  import numpy as np
6
+ from tqdm.auto import tqdm
7
  from sentence_transformers import SentenceTransformer
8
  import zipfile
9
  import xml.etree.ElementTree as ET
 
 
10
 
11
+ DATA_DIR = "/app/dados"
12
+ EXTRACT_DIR = "/app/dados_extraidos"
 
 
 
 
 
 
 
 
 
13
 
14
  def setup_data():
 
15
  os.makedirs(EXTRACT_DIR, exist_ok=True)
16
+ zip_files = glob.glob(DATA_DIR + "/**/*.zip", recursive=True)
17
  if not zip_files:
18
  print("Nenhum arquivo .zip encontrado, usando o diretório de dados principal.")
19
  return DATA_DIR
20
  for zip_path in zip_files:
21
+ print(f"Descompactando {zip_path}...")
22
  with zipfile.ZipFile(zip_path, 'r') as zf:
23
  zf.extractall(EXTRACT_DIR)
24
  return EXTRACT_DIR
25
 
26
  def xml_to_dict(element):
 
27
  d = {}
28
  for child in element:
29
  child_dict = xml_to_dict(child)
 
38
  return d
39
 
40
  def serialize_item_to_text(item_dict):
 
41
  parts = []
42
  if not isinstance(item_dict, dict):
43
  return str(item_dict)
 
52
  parts.append(f"{key}: {value}")
53
  return ", ".join(parts)
54
 
55
+ def main():
 
 
 
 
 
 
 
 
56
  process_dir = setup_data()
 
57
  csv.field_size_limit(10_000_000)
58
+
59
+ all_files = glob.glob(process_dir + "/**/*.json", recursive=True) + \
60
+ glob.glob(process_dir + "/**/*.csv", recursive=True) + \
61
+ glob.glob(process_dir + "/**/*.xml", recursive=True)
62
+ print(f"\n🔎 Encontrados {len(all_files)} arquivos (JSON, CSV, XML) para processar.")
63
+
64
+ if not all_files:
65
+ return
66
 
67
  documents = []
68
+ for filepath in tqdm(all_files, desc="Processando arquivos"):
69
  try:
 
 
 
70
  if filepath.endswith('.json'):
71
  with open(filepath, 'r', encoding='utf-8') as f:
72
  data = json.load(f)
 
84
  xml_dict = {root.tag: xml_to_dict(root)}
85
  documents.append(serialize_item_to_text(xml_dict))
86
  except Exception as e:
87
+ print(f"⚠️ Erro ao processar o arquivo {filepath}: {e}")
88
 
89
+ print(f"\nProcessamento de arquivos concluído! {len(documents)} documentos foram criados.")
90
  if not documents:
 
91
  return
92
 
93
+ cache_path = os.environ.get('SENTENCE_TRANSFORMERS_HOME', '/app/cache/torch')
94
+
95
+ print("Carregando modelo de alta performance: intfloat/multilingual-e5-large")
96
+ model = SentenceTransformer(
97
+ 'intfloat/multilingual-e5-large',
98
+ cache_folder=cache_path
99
+ )
100
+
101
+ batch_size = 128
102
+ output_filename = '/app/output/meus_embeddings_e5_large.npy'
103
 
104
+ if os.path.exists(output_filename):
105
+ os.remove(output_filename)
106
+
107
+ print(f"🚀 Iniciando geração de embeddings (lotes de {batch_size}).")
108
+ for i in tqdm(range(0, len(documents), batch_size), desc="Gerando Embeddings"):
109
+ batch = documents[i:i + batch_size]
110
+ batch_embeddings = model.encode(batch, show_progress_bar=False)
111
+ with open(output_filename, 'ab') as f_out:
112
+ np.save(f_out, batch_embeddings)
113
+
114
+ print(f"✅ Processo finalizado! Embeddings salvos em '{output_filename}'.")
115
+
116
+ if __name__ == "__main__":
117
+ main()