SignalMod / README.es.md
Ruperth's picture
docs: rewrite readmes with logo description architecture and language toggle
ea0e222
SignalMod

Moderación inteligente para comentarios de YouTube

🌐 English · Español

Python FastAPI React Vite PyTorch Transformers scikit-learn Supabase Docker Render


Descripción del proyecto

SignalMod es un asistente de moderación inteligente para comentarios de YouTube. Clasifica automáticamente cada comentario como Seguro o Tóxico, devuelve una probabilidad entre 0 y 1 y etiqueta categorías de toxicidad (insulto, amenaza, odio identitario, contenido obsceno).

Está construido alrededor del modelo hybrid meta-feature stacking del equipo — embeddings de Toxic-BERT congelado combinados con metadatos y una regresión logística regularizada — que alcanza F1 = 0,805 con una brecha train–test de 2,54 pp sobre el split de 200 muestras del proyecto.

El producto se entrega como una API REST con FastAPI y una SPA React que imita la experiencia de YouTube Watch: eliges un vídeo, la API descarga los 50 comentarios más recientes vía la YouTube Data API, los puntúa y persiste cada predicción en Supabase para que cualquier visitante pueda ver el histórico completo.


Herramientas y lenguajes

Lenguajes

  • Python 3.12 — backend, pipelines de ML, evaluación.
  • TypeScript + React 18 — SPA del frontend.
  • SQL (PostgreSQL vía Supabase) — persistencia de predicciones.

Backend

  • FastAPI 0.136 — API REST, esquemas Pydantic, carga del modelo en lifespan.
  • Uvicorn — servidor ASGI con hot reload.
  • scikit-learn 1.8 — baseline TF-IDF + meta-learner LogisticRegression.
  • Optuna — búsqueda de hiperparámetros del baseline TF-IDF.
  • PyTorch 2.x + Transformers 5.9unitary/toxic-bert congelado para embeddings CLS.
  • spaCy + NLTK — lematización, stopwords, limpieza basada en regex.
  • MLflow — tracking de experimentos.
  • Supabase Python SDK — persistencia de predicciones con políticas RLS anónimas.
  • google-api-python-client — integración con YouTube Data API v3.

Frontend

  • React 18 + Vite 5 + TypeScript — SPA con hot module reload.
  • CSS modules — tema oscuro estilo YouTube.

Tooling y operaciones

  • uv — gestor de paquetes y entorno virtual de Python (pyproject.toml + uv.lock).
  • pnpm — gestor de paquetes del frontend.
  • Docker + Docker Compose — despliegue en un único contenedor sirviendo API + SPA construida.
  • GNU Makemake dev, make install, make build, make docker.
  • Render — despliegue gratuito vía blueprint render.yaml.
  • Pytest — tests unitarios de contratos de API y preprocesado.

Arquitectura del proyecto

Project_9_Equipo3/
├── configs/                       # Configs YAML para pipelines y catálogo de inferencia
│   ├── pipeline.yaml              # Rutas de datos, target, folds de CV
│   ├── features.yaml              # Preprocesado y ajustes de TF-IDF
│   ├── model_catalog.yaml         # Catálogo de inferencia (3 modelos intercambiables)
│   ├── best_params.yaml           # Ganador de Optuna para el baseline LR
│   ├── suggested_videos.yaml      # IDs de YouTube del rail "Up next"
│   └── *_training.yaml            # Perfiles de entrenamiento (golden, expert, hybrid, …)
├── data/                          # Datasets crudos y procesados (git-ignored)
├── docs/                          # API.md, PIPELINE.md, ARCHITECTURE.md, DEPLOY.md
│   └── assets/signalmod_logo.png  # Activos de marca
├── frontend/                      # SPA React + Vite
│   ├── public/signalmod_logo.png  # Logo servido como activo estático
│   └── src/
│       ├── api/                   # Cliente HTTP tipado
│       ├── components/            # Layout, CommentRow, SuggestedRail, ModelBanner
│       ├── context/               # Estado global (modelo activo, umbral)
│       ├── hooks/                 # useDebouncedPredict
│       ├── pages/                 # WatchPage, HubPage, SettingsPage
│       └── utils/                 # toxicityColor, randomUsername, relativeTime
├── models/
│   ├── baseline/lr_tfidf.joblib   # Baseline LR ajustado con Optuna
│   └── production_final/          # meta_stack_final.joblib — artefacto de producción
├── notebooks/
│   ├── 01–04                      # EDA, preprocesado, TF-IDF, baseline LR
│   ├── 12                         # Golden baseline (Toxic-BERT congelado)
│   ├── 14                         # Meta-stacking final — artefacto de producción
│   └── archive_attempts/          # Experimentos anteriores conservados para reproducibilidad
├── reports/                       # Métricas, gráficos, figuras EDA, summary.csv
├── src/
│   ├── api/                       # App FastAPI
│   │   ├── main.py                # Lifespan, CORS, montaje del SPA estático
│   │   ├── routes/                # health, models, predict (+ /predictions), videos
│   │   ├── schemas.py             # Modelos Pydantic request/response
│   │   ├── services.py            # predict_single, to_predict_response
│   │   ├── state.py               # Estado compartido de la app
│   │   └── youtube.py             # Fetch a YouTube Data API + metadatos sugeridos
│   ├── data/                      # Loader, dual loader para pipelines híbridos
│   ├── db/                        # Cliente Supabase + helpers save_prediction
│   ├── evaluation/                # Evaluator, threshold tuning, CV estable
│   ├── experiments/               # Versiones script de los notebooks 13 / 14
│   ├── features/                  # text_preprocessor, vectorizer, metadata, augmentation
│   ├── models/                    # baseline (LR/RF/XGBoost), hybrid_ensemble, metadata_lr
│   ├── pipeline/                  # run_pipeline + variantes por estrategia
│   ├── service/                   # ModelService, meta_stack_predictor, model_catalog
│   └── utils/                     # Logger
├── supabase/predictions_setup.sql # SQL para crear la tabla predictions + políticas RLS
├── tests/                         # Suite Pytest
├── Dockerfile                     # Build multi-stage (frontend + backend con uv)
├── docker-compose.yml             # Despliegue de un contenedor (API + SPA)
├── render.yaml                    # Blueprint de Render (web service + static site)
├── Procfile                       # Declaración de proceso para Render
├── Makefile                       # make dev / install / build / docker / test
├── pyproject.toml + uv.lock       # Dependencias Python fijadas con uv
└── README.md  /  README.es.md     # Documentación en inglés / español

Flujo de datos

                ┌────────────────────────────────────────────────┐
                │  SPA React (Vite)         http://localhost:5173│
                │  Layout · Watch · Hub · Settings               │
                └──────────────────┬─────────────────────────────┘
                                   │ HTTP JSON  (proxy Vite → :8000)
                ┌──────────────────▼─────────────────────────────┐
                │  FastAPI                  http://localhost:8000│
                │  /predict  /predict-batch  /predict-video      │
                │  /predictions (GET — histórico de Supabase)    │
                │  /models  /models/select  /model-info          │
                │  /videos/suggested  /health                    │
                └──────┬─────────────────────────────┬───────────┘
                       │                             │
        ┌──────────────▼─────────────┐ ┌─────────────▼──────────────┐
        │  ModelService              │ │  YouTube Data API v3       │
        │  · local joblib            │ │  · metadatos de vídeo      │
        │  · hf_remote               │ │  · 50 comentarios + nuevos │
        │  · meta_stack (producción) │ │                            │
        └──────┬─────────────────────┘ └────────────────────────────┘
               │
        ┌──────▼──────────────────────────────────────────────────┐
        │  Supabase (PostgreSQL)                                  │
        │  tabla: predictions(id, created_at, text, video_id,     │
        │                     probability, is_toxic, labels, …)   │
        │  RLS: insert anónimo + select anónimo                   │
        └─────────────────────────────────────────────────────────┘

Catálogo de modelos (intercambiable desde la UI)

Modelo Tipo F1 (test) Brecha train–test Umbral Latencia Default
Meta-Feature Stacking Híbrido 0,805 2,54 pp 0,381 ~400 ms
Frozen Toxic-BERT Transformer 0,790 0,16 pp 0,120 ~400 ms No
LR + TF-IDF (Optuna) sklearn 0,758 4,76 pp 0,500 < 50 ms No

El modelo de producción concatena el embedding [CLS] congelado de unitary/toxic-bert (768-d) con metadatos hechos a mano (longitud, ratio de mayúsculas, densidad de emojis…), los escala con StandardScaler y los pasa por un meta-learner LogisticRegression(C=0,001).


Instalación y ejecución

1. Requisitos previos

Herramienta macOS / Linux Windows
Python 3.12 brew install python@3.12 python.org/downloads (marca Add Python to PATH)
uv curl -LsSf https://astral.sh/uv/install.sh | sh powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
Node.js 18+ brew install node nodejs.org (LTS)
pnpm npm i -g pnpm npm i -g pnpm
Make (opcional) ya instalado winget install GnuWin32.Make (o usa WSL)

2. Clonar y configurar

git clone https://github.com/Bootcamp-IA-P6/Project_9_Equipo3.git
cd Project_9_Equipo3

cp .env.example .env
# Rellena: YOUTUBE_API_KEY, SUPABASE_URL, SUPABASE_KEY

PowerShell de Windows: sustituye cp por Copy-Item .env.example .env.

Pega supabase/predictions_setup.sql en el editor SQL de Supabase antes del primer arranque (crea la tabla predictions + políticas RLS).

3. Arranque — tres opciones

Opción A — Con Makefile (recomendada en macOS / Linux / WSL)

make install     # uv sync  +  pnpm install
make dev         # FastAPI :8000  +  Vite :5173
Comando Qué hace
make install Instala deps de Python + frontend
make dev Arranca API y UI en paralelo (Ctrl+C los para)
make api Solo la API
make ui Solo la UI
make build Compila el SPA a frontend/dist
make test Ejecuta Pytest
make docker docker compose up --build
make stop Mata procesos en los puertos 8000 / 5173
make clean Borra .venv, node_modules, dist

Opción B — Manual (macOS / Linux)

Dos terminales.

Terminal 1 — API

uv sync
uv run uvicorn src.api.main:app --reload --port 8000

Terminal 2 — Frontend

cd frontend
pnpm install
pnpm dev

Opción C — Manual (PowerShell de Windows)

Dos terminales.

Terminal 1 — API

uv sync
uv run uvicorn src.api.main:app --reload --port 8000

Terminal 2 — Frontend

cd frontend
pnpm install
pnpm dev

Si uv no se reconoce tras instalarlo, cierra y vuelve a abrir PowerShell para que se recargue el PATH.

4. Abrir la aplicación

URL Qué verás
http://localhost:5173 SPA React — Watch / Hub / Settings
http://localhost:8000/docs Swagger de FastAPI
http://localhost:8000/health Health check

5. Docker (un solo contenedor — API + SPA compilada)

Mismos comandos en macOS / Linux / Windows:

# Normal — deja imágenes y volúmenes para builds rápidos
docker compose up --build
# → http://localhost:8000  ·  Ctrl+C para parar  ·  docker compose down

# Demo efímera — Ctrl+C borra contenedor + imagen + volúmenes
make docker-demo

# Limpieza manual completa
make docker-clean
# (equivale a: docker compose down --rmi local --volumes --remove-orphans)

Más detalle: docs/PIPELINE.es.md para entrenamiento, docs/API.es.md para endpoints, docs/DEPLOY.md para despliegue en Render.


Colaboradores

Andrés Torrez
Backend Developer
Mirae Kang
Scrum Master
Jonathan Brasales
AI Developer
Roberto Molero
Product Owner

SignalMod — Bootcamp IA P6 · Equipo 3 · 2026