Spaces:
Build error
Build error
| # --- 1. IMPORTS --- | |
| # Imports do seu train.py e do Gradio | |
| import os | |
| import glob | |
| import json | |
| import csv | |
| import numpy as np | |
| from sentence_transformers import SentenceTransformer | |
| import zipfile | |
| import xml.etree.ElementTree as ET | |
| import gradio as gr | |
| import shutil | |
| # --- 2. CONFIGURAÇÕES E CONSTANTES --- | |
| # Caminhos relativos são melhores para portabilidade no Hugging Face Spaces | |
| DATA_DIR = "dados" | |
| EXTRACT_DIR = os.path.join(DATA_DIR, "dados_extraidos") | |
| # ATIVA O ARMAZENAMENTO PERSISTENTE NAS CONFIGURAÇÕES DO SEU SPACE! | |
| # Se ativado, mude o caminho para algo como "/data/meus_embeddings.npy" | |
| OUTPUT_FILENAME = "meus_embeddings_e5_large.npy" | |
| # --- 3. SUAS FUNÇÕES DE PROCESSAMENTO (DO TRAIN.PY) --- | |
| # Copiamos suas funções de ajuda diretamente para cá. | |
| def setup_data(): | |
| """Descompacta os arquivos .zip e retorna o diretório de processamento.""" | |
| os.makedirs(EXTRACT_DIR, exist_ok=True) | |
| zip_files = glob.glob(os.path.join(DATA_DIR, "*.zip")) # Simplificado para buscar zips na pasta 'dados' | |
| if not zip_files: | |
| print("Nenhum arquivo .zip encontrado, usando o diretório de dados principal.") | |
| return DATA_DIR | |
| for zip_path in zip_files: | |
| with zipfile.ZipFile(zip_path, 'r') as zf: | |
| zf.extractall(EXTRACT_DIR) | |
| return EXTRACT_DIR | |
| def xml_to_dict(element): | |
| """Converte um elemento XML para um dicionário Python.""" | |
| d = {} | |
| for child in element: | |
| child_dict = xml_to_dict(child) | |
| if child.tag in d: | |
| if not isinstance(d[child.tag], list): | |
| d[child.tag] = [d[child.tag]] | |
| d[child.tag].append(child_dict) | |
| else: | |
| d[child.tag] = child_dict | |
| if not d: | |
| return element.text | |
| return d | |
| def serialize_item_to_text(item_dict): | |
| """Converte um dicionário (de JSON, CSV, etc.) para uma string de texto plano.""" | |
| parts = [] | |
| if not isinstance(item_dict, dict): | |
| return str(item_dict) | |
| for key, value in item_dict.items(): | |
| if isinstance(value, dict): | |
| nested_text = serialize_item_to_text(value) | |
| parts.append(f"{key} ({nested_text})") | |
| elif isinstance(value, list): | |
| list_str = ', '.join([serialize_item_to_text(i) for i in value]) | |
| parts.append(f"{key}: [{list_str}]") | |
| else: | |
| parts.append(f"{key}: {value}") | |
| return ", ".join(parts) | |
| # --- 4. FUNÇÃO ORQUESTRADORA (LÓGICA PRINCIPAL) --- | |
| # Esta função substitui a sua função `main()` e é chamada pelo Gradio. | |
| # Ela usa `yield` para enviar atualizações de progresso para a interface. | |
| def run_full_process(): | |
| """Executa o pipeline completo e envia o progresso para a UI.""" | |
| # --- ETAPA 1: SETUP E PROCESSAMENTO DE ARQUIVOS --- | |
| yield "Iniciando... Descompactando arquivos..." | |
| process_dir = setup_data() | |
| csv.field_size_limit(10_000_000) | |
| all_files = glob.glob(os.path.join(process_dir, "**/*.json"), recursive=True) + \ | |
| glob.glob(os.path.join(process_dir, "**/*.csv"), recursive=True) + \ | |
| glob.glob(os.path.join(process_dir, "**/*.xml"), recursive=True) | |
| yield f"🔎 Encontrados {len(all_files)} arquivos para processar." | |
| documents = [] | |
| for idx, filepath in enumerate(all_files): | |
| try: | |
| # Mostra o progresso na interface em vez de usar tqdm | |
| yield f"Processando arquivo {idx + 1}/{len(all_files)}: {os.path.basename(filepath)}" | |
| if filepath.endswith('.json'): | |
| with open(filepath, 'r', encoding='utf-8') as f: | |
| data = json.load(f) | |
| if isinstance(data, list): | |
| for item in data: documents.append(serialize_item_to_text(item)) | |
| else: | |
| documents.append(serialize_item_to_text(data)) | |
| elif filepath.endswith('.csv'): | |
| with open(filepath, 'r', encoding='utf-8') as f: | |
| reader = csv.DictReader(f) | |
| for row in reader: documents.append(serialize_item_to_text(row)) | |
| elif filepath.endswith('.xml'): | |
| tree = ET.parse(filepath) | |
| root = tree.getroot() | |
| xml_dict = {root.tag: xml_to_dict(root)} | |
| documents.append(serialize_item_to_text(xml_dict)) | |
| except Exception as e: | |
| yield f"⚠️ Erro ao processar {os.path.basename(filepath)}: {e}" | |
| yield f"Processamento de arquivos concluído! {len(documents)} documentos criados." | |
| if not documents: | |
| yield "Nenhum documento encontrado para gerar embeddings. Processo encerrado." | |
| return | |
| # --- ETAPA 2: GERAÇÃO DE EMBEDDINGS --- | |
| yield "Carregando modelo de alta performance: intfloat/multilingual-e5-large..." | |
| # Use um cache dentro do seu Space para não baixar o modelo toda vez | |
| cache_path = './model_cache' | |
| os.makedirs(cache_path, exist_ok=True) | |
| model = SentenceTransformer('intfloat/multilingual- |