File size: 5,546 Bytes
eaf228d
e58615a
 
 
eaf228d
 
e58615a
eaf228d
 
 
e58615a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9da4e9c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e58615a
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
---
title: Reportes Racing
emoji: 
colorFrom: green
colorTo: gray
sdk: docker
app_port: 7860
pinned: false
---

# Reportes Racing

Web privada para generar los reportes tácticos reales (pre-partido /
head-to-head, post-partido y bloques z-score) sin setup local. La data se
descarga desde Azure Data Lake; nada de datos en el repo.

## Cómo se usa (gente no técnica)

1. Abrir el link del Space (te invitan con tu cuenta de Hugging Face) e
   ingresar la contraseña si la web la pide.
2. **Reporte previo / Bloques**: elegir Equipo A y Equipo B (cualquier par,
   aunque no se hayan jugado), opcionalmente fechas desde/hasta para Bloques,
   y tildar qué reportes querés. Click en *Generar*.
3. **Reporte post-partido**: tocar *Cargar lista de partidos jugados*, elegir
   el partido y *Generar post-partido* (corre también el previo de ese
   partido automáticamente).
4. Aparece una pantalla de progreso que se actualiza sola. Puede tardar
   varios minutos (especialmente la primera vez del día). Al terminar muestra
   los links para **Ver** y **Descargar** cada reporte.

## Deploy en Hugging Face Spaces (privado)

1. Crear un Space tipo **Docker**, visibilidad **Private**.
2. Conectarlo a este repo (o `git push` al remoto del Space).
3. En *Settings → Variables and secrets* cargar los secrets de Azure
   (Service Principal con permiso de lectura sobre el Data Lake):

   ```
   AZURE_TENANT_ID=...
   AZURE_CLIENT_ID=...
   AZURE_CLIENT_SECRET=...
   AZURE_STORAGE_ACCOUNT=stdlprodfrancecentral001
   AZURE_FILESYSTEM=fs-dl-prod-francecentral-001
   AZURE_PREPROCESSED_ROOT=raw/eventing/processed
   AZURE_REPORT_ARTIFACTS_ROOT=raw/eventing/report_artifacts
   ACCESS_PASSWORD=una-clave-compartida   # opcional, candado extra
   ```

4. Build automático. El disco del Space es efímero: en un arranque en frío se
   vuelven a descargar los datasets desde Azure (lento la primera vez, luego
   queda cacheado mientras el Space siga vivo).

Invitar a la gente al Space privado = control de acceso.

## Uso local (desarrollo)

```bash
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cp .env.sample .env        # editar credenciales
az login                   # auth local (sin Service Principal)
racing-reports-web         # http://127.0.0.1:7860
```

Para correr sin Azure (con datos ya locales) exportar
`RACING_LOCAL_DATA_DIR=/ruta/con/preprocessed+artifacts`.

## Prerrequisito de datos en Azure

Los reportes reales necesitan, además del preprocessed base, artifacts
pesados y el preprocessed **etiquetado**. Subirlos una vez con:

```bash
python scripts/upload_report_artifacts.py            # parquets + bundles GNN
python ../scripts/upload_preprocessed_labeled.py \
    --local-path /ruta/preprocessed_..._etiquetado_final.csv \
    --remote-name preprocessed_SSD_25-26_etiquetado_modelo.csv
```

## Modelo de predicción de ataque (matchup GNN)

El reporte previo / head-to-head puede mostrar la **distribución de ataque
esperada por zona** (local y visitante) según un modelo de red neuronal. El
modelo de producción es el **matchup GNN** (`train_attack_matchup_gnn.py`), que
reemplaza al viejo `attack_distribution_gnn`: selecciona ~200 features de alta
señal (en vez de ~950, atacando el sobreajuste), agrega una interacción bilineal
explícita atacante × defensor por zona, y aprende un *delta* sobre el promedio
del equipo. En test le gana al baseline "promedio de temporada" de forma
estadísticamente robusta (IC bootstrap del 95% que excluye el cero).

Las predicciones están **apagadas por defecto** (MVP). Hay dos formas de servir
los artifacts del modelo; en ambas se activa con el secret
`RR_ENABLE_NN_PREDICTIONS=1` en el Space.

**Opción A — bundlear en el repo (sin Azure, recomendada).** El datastore usa los
artifacts reales de `vendor/data/modeling/` antes de ir a Azure. Como la app
recalcula los rolling al vuelo desde las columnas crudas, el dataset se recorta de
**71 MB → ~10 MB** sin cambiar ninguna predicción:

```bash
python ../scripts/build_app_modeling_subset.py --copy-bundles
git add racing-reports/vendor/data/modeling/{attack_prediction_dataset.parquet,attack_matchup_gnn_bundle.pt,pv_distribution_gnn_bundle.pt}
git commit -m "bundle modelo de ataque"   # parquet ~10 MB: usar git-lfs si tu remoto lo pide
```

En el próximo arranque la app usa esos archivos directamente, sin tocar Azure.

**Opción B — subir a Azure.** Si preferís no commitear artifacts:

```bash
RR_ENABLE_NN_PREDICTIONS=1 python scripts/upload_report_artifacts.py --source /ruta/Racing/data --overwrite
```

En el cold start la app descarga `modeling/attack_matchup_gnn_bundle.pt` (y el de
PV + el dataset) desde Azure.

## Actualizar la data y el modelo (pipeline)

Un solo orquestador idempotente encadena todo el ciclo, desde los eventos crudos
hasta el bundle publicado que consume la app:

```bash
python ../scripts/run_attack_model_pipeline.py            # todo (saltea lo que ya está al día)
python ../scripts/run_attack_model_pipeline.py --list     # ver los stages
python ../scripts/run_attack_model_pipeline.py --only train --train-args "--top-k 200 --seeds 3"
python ../scripts/run_attack_model_pipeline.py --from dataset --force
```

Stages: `events``zone_features``dataset``rolling``train``publish`.
Los stages `events` y `publish` requieren credenciales de Azure.

## Salida

```text
{RACING_REPORTS_OUTPUT_DIR}/{league}/{season}/{slug}/{report}.html
{RACING_REPORTS_OUTPUT_DIR}/{league}/{season}/{slug}/manifest.json
```