Edoruin commited on
Commit
fad9b47
·
1 Parent(s): bd57b26

fix secrets no found

Browse files
Files changed (4) hide show
  1. SETUP_PERSISTENCE.md +72 -0
  2. app/main.py +37 -6
  3. migrate_data.py +105 -0
  4. setup_datasets.py +93 -0
SETUP_PERSISTENCE.md ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🔧 Configuración de Persistencia de Datos
2
+
3
+ Este directorio contiene scripts para configurar la persistencia de datos usando Hugging Face Datasets.
4
+
5
+ ## 📋 Problema
6
+
7
+ Cuando haces un **factory rebuild** en Hugging Face Spaces, todos los datos se pierden porque el contenedor se recrea desde cero.
8
+
9
+ ## ✅ Solución
10
+
11
+ Usar Hugging Face Datasets para almacenar los datos de forma permanente.
12
+
13
+ ## 🚀 Pasos Rápidos
14
+
15
+ ### 1️⃣ Crear los Datasets (Una sola vez)
16
+
17
+ Ejecuta desde tu máquina local:
18
+
19
+ ```bash
20
+ python3 setup_datasets.py
21
+ ```
22
+
23
+ Esto creará 4 datasets privados en tu cuenta de Hugging Face:
24
+ - `Edoruin/makerpage-users`
25
+ - `Edoruin/makerpage-classrooms`
26
+ - `Edoruin/makerpage-loans`
27
+ - `Edoruin/makerpage-faces`
28
+
29
+ ### 2️⃣ Configurar Secretos en HF Spaces
30
+
31
+ Ve a tu Space → **Settings** → **Repository secrets** y agrega:
32
+
33
+ ```
34
+ HF_TOKEN=hf_tu_token_aqui
35
+ HF_DATASET_USERS=Edoruin/makerpage-users
36
+ HF_DATASET_CLASSROOMS=Edoruin/makerpage-classrooms
37
+ HF_DATASET_LOANS=Edoruin/makerpage-loans
38
+ HF_DATASET_FACES=Edoruin/makerpage-faces
39
+ ```
40
+
41
+ ### 3️⃣ Migrar Datos Existentes (Opcional)
42
+
43
+ Si ya tienes datos que quieres preservar, ejecuta desde el Space:
44
+
45
+ ```bash
46
+ python migrate_data.py
47
+ ```
48
+
49
+ ### 4️⃣ Reiniciar
50
+
51
+ Haz **restart** (no factory rebuild) del Space.
52
+
53
+ ## ✨ Verificación
54
+
55
+ Revisa los logs del Space. Deberías ver:
56
+
57
+ ```
58
+ [UserManager] HF Datasets: ENABLED
59
+ [ClassroomManager] HF Datasets: ENABLED
60
+ [LoanManager] HF Datasets: ENABLED
61
+ [FaceManager] HF Datasets: ENABLED
62
+ ```
63
+
64
+ ## 🎉 ¡Listo!
65
+
66
+ Ahora puedes hacer factory rebuild sin perder datos. Todo se guarda automáticamente en Hugging Face Datasets.
67
+
68
+ ## 📝 Notas
69
+
70
+ - Los datasets son **privados** por defecto
71
+ - Los datos se guardan en local (backup) y en HF (persistente)
72
+ - Necesitas un token de Hugging Face con permisos de escritura
app/main.py CHANGED
@@ -269,13 +269,30 @@ class ClassroomManager(HFDatasetManager):
269
  self.classrooms = self._load()
270
 
271
  def _load(self):
272
- data = super()._load_from_hf() if self.use_hf else super()._load_from_local()
273
- return data if data else []
 
 
 
 
 
 
 
 
 
274
 
275
  def save(self):
276
- if self.use_hf:
277
- self._save_to_hf(self.classrooms)
278
  self._save_to_local(self.classrooms)
 
 
 
 
 
 
 
 
279
 
280
  def get_courses(self):
281
  return self.classrooms
@@ -426,16 +443,30 @@ class FaceManager(HFDatasetManager):
426
  self.faces = self._load()
427
 
428
  def _load(self):
 
429
  if self.use_hf:
430
  data = self._load_from_hf()
431
  if data is not None:
 
432
  return data
433
- return self._load_from_local()
 
 
 
 
434
 
435
  def save(self):
 
 
436
  self._save_to_local(self.faces)
 
 
437
  if self.use_hf:
438
- self._save_to_hf(self.faces)
 
 
 
 
439
 
440
  def add_face(self, label, descriptor):
441
  # El descriptor es una lista de 128 floats (face-api.js)
 
269
  self.classrooms = self._load()
270
 
271
  def _load(self):
272
+ """Carga los cursos desde HF Dataset o archivo JSON local."""
273
+ if self.use_hf:
274
+ data = self._load_from_hf()
275
+ if data is not None:
276
+ print(f"[ClassroomManager] Loaded {len(data)} courses from HF Dataset")
277
+ return data
278
+ print("[ClassroomManager] Failed to load from HF, trying local...")
279
+
280
+ data = self._load_from_local()
281
+ print(f"[ClassroomManager] Loaded {len(data)} courses from local JSON")
282
+ return data
283
 
284
  def save(self):
285
+ """Guarda la lista de cursos en HF Dataset y/o archivo JSON."""
286
+ # Siempre guardar localmente como backup
287
  self._save_to_local(self.classrooms)
288
+
289
+ # Intentar guardar en HF si está habilitado
290
+ if self.use_hf:
291
+ success = self._save_to_hf(self.classrooms)
292
+ if success:
293
+ print(f"[ClassroomManager] Saved {len(self.classrooms)} courses to HF Dataset")
294
+ else:
295
+ print("[ClassroomManager] Failed to save to HF, data saved locally only")
296
 
297
  def get_courses(self):
298
  return self.classrooms
 
443
  self.faces = self._load()
444
 
445
  def _load(self):
446
+ """Carga los rostros desde HF Dataset o archivo JSON local."""
447
  if self.use_hf:
448
  data = self._load_from_hf()
449
  if data is not None:
450
+ print(f"[FaceManager] Loaded {len(data)} faces from HF Dataset")
451
  return data
452
+ print("[FaceManager] Failed to load from HF, trying local...")
453
+
454
+ data = self._load_from_local()
455
+ print(f"[FaceManager] Loaded {len(data)} faces from local JSON")
456
+ return data
457
 
458
  def save(self):
459
+ """Guarda la lista de rostros en HF Dataset y/o archivo JSON."""
460
+ # Siempre guardar localmente como backup
461
  self._save_to_local(self.faces)
462
+
463
+ # Intentar guardar en HF si está habilitado
464
  if self.use_hf:
465
+ success = self._save_to_hf(self.faces)
466
+ if success:
467
+ print(f"[FaceManager] Saved {len(self.faces)} faces to HF Dataset")
468
+ else:
469
+ print("[FaceManager] Failed to save to HF, data saved locally only")
470
 
471
  def add_face(self, label, descriptor):
472
  # El descriptor es una lista de 128 floats (face-api.js)
migrate_data.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script para migrar datos locales existentes a Hugging Face Datasets.
4
+ Ejecutar DESPUÉS de crear los datasets vacíos con setup_datasets.py
5
+ """
6
+
7
+ import os
8
+ import json
9
+ from datasets import Dataset
10
+ from dotenv import load_dotenv
11
+
12
+ load_dotenv()
13
+
14
+ # Configuración
15
+ HF_TOKEN = os.getenv("HF_TOKEN")
16
+ USERNAME = "Edoruin"
17
+
18
+ # Mapeo de archivos locales a datasets
19
+ MIGRATIONS = [
20
+ {
21
+ "local_file": "/app/data/users.json",
22
+ "dataset_name": f"{USERNAME}/makerpage-users",
23
+ "data_key": "users",
24
+ "description": "Usuarios"
25
+ },
26
+ {
27
+ "local_file": "/app/data/classrooms.json",
28
+ "dataset_name": f"{USERNAME}/makerpage-classrooms",
29
+ "data_key": "classrooms",
30
+ "description": "Aulas/Cursos"
31
+ },
32
+ {
33
+ "local_file": "/app/data/prestamos.json",
34
+ "dataset_name": f"{USERNAME}/makerpage-loans",
35
+ "data_key": "loans",
36
+ "description": "Préstamos"
37
+ },
38
+ {
39
+ "local_file": "/app/data/faces.json",
40
+ "dataset_name": f"{USERNAME}/makerpage-faces",
41
+ "data_key": "faces",
42
+ "description": "Rostros"
43
+ }
44
+ ]
45
+
46
+ def migrate_file(local_file, dataset_name, data_key, description):
47
+ """Migra un archivo JSON local a un dataset de HF."""
48
+
49
+ # Verificar si el archivo existe
50
+ if not os.path.exists(local_file):
51
+ print(f"⚠️ {description}: Archivo no encontrado ({local_file}), usando datos vacíos")
52
+ data = []
53
+ else:
54
+ # Leer datos locales
55
+ try:
56
+ with open(local_file, 'r') as f:
57
+ data = json.load(f)
58
+ print(f"📂 {description}: {len(data)} registros encontrados")
59
+ except Exception as e:
60
+ print(f"❌ {description}: Error leyendo archivo - {e}")
61
+ return False
62
+
63
+ # Subir a Hugging Face
64
+ try:
65
+ dataset_dict = {data_key: [data]}
66
+ dataset = Dataset.from_dict(dataset_dict)
67
+ dataset.push_to_hub(
68
+ dataset_name,
69
+ token=HF_TOKEN,
70
+ private=True
71
+ )
72
+ print(f"✅ {description}: Migrado exitosamente a {dataset_name}\n")
73
+ return True
74
+
75
+ except Exception as e:
76
+ print(f"❌ {description}: Error subiendo a HF - {e}\n")
77
+ return False
78
+
79
+ def main():
80
+ if not HF_TOKEN:
81
+ print("❌ ERROR: No se encontró HF_TOKEN")
82
+ return
83
+
84
+ print("🔄 Iniciando migración de datos locales a Hugging Face Datasets\n")
85
+ print("=" * 60)
86
+
87
+ success_count = 0
88
+ for migration in MIGRATIONS:
89
+ if migrate_file(**migration):
90
+ success_count += 1
91
+
92
+ print("=" * 60)
93
+ print(f"\n✨ Migración completada: {success_count}/{len(MIGRATIONS)} datasets actualizados")
94
+
95
+ if success_count == len(MIGRATIONS):
96
+ print("\n🎉 ¡Todos los datos han sido migrados exitosamente!")
97
+ print("\n📋 Próximos pasos:")
98
+ print("1. Reinicia tu Hugging Face Space")
99
+ print("2. Verifica que los datos aparezcan correctamente")
100
+ print("3. Ahora puedes hacer factory rebuild sin perder datos")
101
+ else:
102
+ print("\n⚠️ Algunos datasets no se pudieron migrar. Revisa los errores arriba.")
103
+
104
+ if __name__ == "__main__":
105
+ main()
setup_datasets.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script para inicializar los datasets de Hugging Face con datos vacíos.
4
+ Ejecutar SOLO UNA VEZ para crear los datasets iniciales.
5
+ """
6
+
7
+ import os
8
+ from datasets import Dataset
9
+ from huggingface_hub import HfApi
10
+ from dotenv import load_dotenv
11
+
12
+ load_dotenv()
13
+
14
+ # Configuración
15
+ HF_TOKEN = os.getenv("HF_TOKEN")
16
+ USERNAME = "Edoruin" # Tu usuario de Hugging Face
17
+
18
+ # Datasets a crear
19
+ DATASETS = {
20
+ "users": {
21
+ "name": f"{USERNAME}/makerpage-users",
22
+ "data_key": "users",
23
+ "initial_data": []
24
+ },
25
+ "classrooms": {
26
+ "name": f"{USERNAME}/makerpage-classrooms",
27
+ "data_key": "classrooms",
28
+ "initial_data": []
29
+ },
30
+ "loans": {
31
+ "name": f"{USERNAME}/makerpage-loans",
32
+ "data_key": "loans",
33
+ "initial_data": []
34
+ },
35
+ "faces": {
36
+ "name": f"{USERNAME}/makerpage-faces",
37
+ "data_key": "faces",
38
+ "initial_data": []
39
+ }
40
+ }
41
+
42
+ def create_dataset(dataset_name, data_key, initial_data):
43
+ """Crea un dataset vacío en Hugging Face Hub."""
44
+ try:
45
+ # Crear dataset con estructura inicial
46
+ dataset_dict = {data_key: [initial_data]}
47
+ dataset = Dataset.from_dict(dataset_dict)
48
+
49
+ # Subir a Hugging Face Hub
50
+ dataset.push_to_hub(
51
+ dataset_name,
52
+ token=HF_TOKEN,
53
+ private=True # Dataset privado
54
+ )
55
+
56
+ print(f"✅ Dataset creado: {dataset_name}")
57
+ return True
58
+
59
+ except Exception as e:
60
+ print(f"❌ Error creando {dataset_name}: {e}")
61
+ return False
62
+
63
+ def main():
64
+ if not HF_TOKEN:
65
+ print("❌ ERROR: No se encontró HF_TOKEN en las variables de entorno")
66
+ print(" Asegúrate de tener un archivo .env con HF_TOKEN=tu_token")
67
+ return
68
+
69
+ print(f"🚀 Iniciando creación de datasets para usuario: {USERNAME}\n")
70
+
71
+ for key, config in DATASETS.items():
72
+ print(f"📦 Creando dataset: {config['name']}")
73
+ create_dataset(
74
+ config['name'],
75
+ config['data_key'],
76
+ config['initial_data']
77
+ )
78
+ print()
79
+
80
+ print("✨ Proceso completado!")
81
+ print("\n📋 Próximos pasos:")
82
+ print("1. Ve a Hugging Face Spaces → Settings → Repository secrets")
83
+ print("2. Verifica que estos secretos estén configurados:")
84
+ print(f" - HF_TOKEN = {HF_TOKEN[:10]}...")
85
+ print(f" - HF_DATASET_USERS = {DATASETS['users']['name']}")
86
+ print(f" - HF_DATASET_CLASSROOMS = {DATASETS['classrooms']['name']}")
87
+ print(f" - HF_DATASET_LOANS = {DATASETS['loans']['name']}")
88
+ print(f" - HF_DATASET_FACES = {DATASETS['faces']['name']}")
89
+ print("\n3. Reinicia tu Space (NO factory rebuild todavía)")
90
+ print("4. Verifica que los logs muestren 'HF Datasets: ENABLED'")
91
+
92
+ if __name__ == "__main__":
93
+ main()