#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Publica o AURORA v7 no HuggingFace de modo ORGANIZADO e COMPLETO: README.md (model card v7 COM GRÁFICOS DE DESEMPENHO) · LICENSE · configs/ · src/aurora/ · scripts/ · docs/matematica/ (provas 00–18) · tests/ · evidências de treino/avaliação/comparação · estados/fase-v7/ (pesos finais + meta SHA-256) REGRAS DO HUB (escopo v5): publicação em UM ÚNICO COMMIT COMPLETO — `upload_folder` com `delete_patterns=["*"]` substitui ATOMICAMENTE todo o conteúdo do repo (arquivos antigos somem no MESMO commit; nunca há uploads parciais em sequência curta — o Hub bloqueia esse padrão). SEGURANÇA: token EXCLUSIVAMENTE da variável HF_TOKEN — nunca gravado em arquivo, log ou repo. A publicação NUNCA inclui: cache_dados, telemetria_out, estados_local, stage_publicar, arquivos com o token. Verificações de porta do Agente Engenheiro (pré-publicação): • nenhum segredo no stage (regex hf_[A-Za-z0-9]{30,}); • nenhum resíduo proibido (bugwatch, estados_hf, __pycache__, .pt). Uso: HF_TOKEN=... python3 06_publicar_hf.py [--repo PowerMachine/aurora-multimodal-ptbr] """ import argparse import os import re import shutil import sys RAIZ = "/home/z/my-project/aurora" STAGE = "/home/z/my-project/aurora/stage_publicar" PASTA_ESTADO = "estados/fase-v7" # ÚNICO estado publicado (pesos finais) IGNORAR_DIRS = {"__pycache__", "cache_dados", "telemetria_out", "cache_hub_tmp", ".git", "build", "estados_local", "estados_local_teste", "stage_publicar", "hf_stage", "download", "upload"} IGNORAR_EXT = (".pt", ".pyc", ".pt.tmp") PADRAO_TOKEN = re.compile(r"hf_[A-Za-z0-9]{30,}") RESIDUOS_PROIBIDOS = ("bugwatch", "estados_hf") def preparar_stage() -> int: if os.path.exists(STAGE): shutil.rmtree(STAGE) n = 0 for raiz, dirs, arquivos in os.walk(RAIZ): dirs[:] = [d for d in dirs if d not in IGNORAR_DIRS] rel = os.path.relpath(raiz, RAIZ) alvo_raiz = os.path.join(STAGE, rel) if rel != "." else STAGE os.makedirs(alvo_raiz, exist_ok=True) for a in arquivos: if a.endswith(IGNORAR_EXT) or a.startswith("."): continue if any(r in a.lower() for r in RESIDUOS_PROIBIDOS): print(f" porta do Agente: arquivo proibido ignorado: {a}") continue shutil.copy2(os.path.join(raiz, a), os.path.join(alvo_raiz, a)) n += 1 # evidências de treino/avaliação (artefatos de 1ª classe, v7) for nome in ("avaliacao_v7.json", "resumo_treino_v7.json", "relatorio_agente_engenheiro.json", "comparacao_treino_v7.json", "test_aurora_v6_pos_treino.txt"): fonte = os.path.join(RAIZ, "telemetria_out", nome) if os.path.exists(fonte): shutil.copy2(fonte, os.path.join(STAGE, nome)) n += 1 # v7 — GRÁFICOS DE DESEMPENHO (publicados APENAS no card HF — README.md) dir_graf = os.path.join(RAIZ, "graficos") if os.path.isdir(dir_graf): os.makedirs(os.path.join(STAGE, "graficos"), exist_ok=True) for a in sorted(os.listdir(dir_graf)): if a.endswith(".png"): shutil.copy2(os.path.join(dir_graf, a), os.path.join(STAGE, "graficos", a)) n += 1 # ÚNICO estado (pesos finais) via GestorCheckpoints (doc 16 §8) sys.path.insert(0, os.path.join(RAIZ, "src")) from aurora.dados.checkpoints import GestorCheckpoints from aurora.config import Config gestor = GestorCheckpoints(dir_local=Config().checkpoints.dir_local, pasta_publicacao=PASTA_ESTADO) if gestor.preparar_para_publicacao(STAGE): n += 2 print(f"estado final incluído: {PASTA_ESTADO}/modelo.safetensors") else: print("AVISO: sem checkpoint local — publicando só código/docs") return n def auditoria_segredos() -> list[str]: suspeitos = [] for raiz, dirs, arquivos in os.walk(STAGE): for a in arquivos: if not a.endswith((".json", ".md", ".py", ".txt", ".yaml", ".yml")): continue caminho = os.path.join(raiz, a) try: with open(caminho, encoding="utf-8", errors="ignore") as f: if PADRAO_TOKEN.search(f.read()): suspeitos.append(caminho) except Exception: pass return suspeitos def main(): ap = argparse.ArgumentParser() ap.add_argument("--repo", default="PowerMachine/aurora-multimodal-ptbr") args = ap.parse_args() token = os.environ.get("HF_TOKEN") if not token: print("ERRO: defina HF_TOKEN no ambiente (nunca em arquivo).") sys.exit(1) n = preparar_stage() print(f"stage: {n} arquivos (sem caches/segredos/resíduos)") suspeitos = auditoria_segredos() if suspeitos: print("ERRO: possíveis segredos detectados:", suspeitos) sys.exit(1) from huggingface_hub import HfApi api = HfApi(token=token) api.create_repo(args.repo, repo_type="model", exist_ok=True, private=False) # PUBLICAÇÃO ÚNICA E COMPLETA: delete_patterns=["*"] remove no MESMO commit # qualquer arquivo antigo — nada de uploads parciais em sequência api.upload_folder( folder_path=STAGE, repo_id=args.repo, repo_type="model", commit_message="AURORA v7 — RETREINO OBSERVADO: estados antigos apagados; " "treino do zero com monitor de RAM integral (Agente Engenheiro); " "métricas de tests/test_aurora_v6.py comparadas com o treino " "anterior; gráficos de desempenho publicados no card", delete_patterns=["*"], allow_patterns=["*.py", "*.md", "*.json", "*.yaml", "*.yml", "*.txt", "*.png", "*.safetensors", "LICENSE*"]) print("✓ PUBLICAÇÃO ÚNICA COMPLETA (1 commit; antigos removidos " "atomicamente)") # verificação final: resíduos proibidos não podem existir no repo arquivos = api.list_repo_files(args.repo, repo_type="model") restos = [f for f in arquivos if any(r in f.lower() for r in RESIDUOS_PROIBIDOS) or "__pycache__" in f or f.endswith(".pt")] if restos: print("ERRO: resíduos no repo:", restos) sys.exit(1) parciais = [f for f in arquivos if f.startswith("estados/") and "fase-v7" not in f] print(f"✓ verificação: {len(arquivos)} arquivos no repo; " f"resíduos=0; estados parciais={len(parciais)} (0 esperado)") print(f"REPO: https://huggingface.co/{args.repo}") print("Higienização: unset HF_TOKEN && python3 -m pip show huggingface_hub " ">/dev/null && python3 -c 'from huggingface_hub import HfApi; " "HfApi().logout()'") if __name__ == "__main__": main()