ML Experiment Accelerator

Notebook experimental → pipeline de 5 pasos → código producción con tests y config MLflow.

El problema

El 85% de modelos ML nunca llegan a producción. Un factor clave: el gap entre el notebook del data scientist y el código production-ready que necesita el pipeline MLOps. El data scientist sabe qué modelo quiere pero no siempre escribe código productizable: sin tests, sin type hints, sin manejo de errores, sin logging, con hyperparams hardcodeados.

Dónde encaja architect

Architect como traductor de notebooks a código producción. El pipeline toma el notebook experimental, genera código limpio siguiendo las convenciones MLOps del equipo (definidas en .architect.md), genera tests, y valida que el training pipeline funcione.

Diagrama

flowchart TD
    A["👩‍🔬 Data Scientist\nNotebook experimental\n(experiment.ipynb)"] --> B["architect pipeline\nml-productionize.yaml"]

    subgraph architect_pipeline["Architect Pipeline"]
        direction TB
        B --> C["Step 1: Extract\nParsea notebook,\nextrae lógica core"]
        C --> D["Step 2: Structure\nGenera módulos:\ndata.py, model.py,\ntrain.py, evaluate.py"]
        D --> E["Step 3: Harden\nAñade type hints,\nerror handling,\nlogging, configs"]
        E --> F["Step 4: Test\nGenera tests +\nejecutalos"]
        F --> G["Step 5: Pipeline\nGenera pipeline\nMLflow/Kubeflow YAML"]
    end

    G --> H["PR con:\n- Código productizado\n- Tests\n- Pipeline config\n- Report"]

    H --> I["ML Engineer Review"]
    I --> J["MLOps Pipeline\n(MLflow / Kubeflow\n/ Vertex AI)"]

    J --> K["Train → Evaluate\n→ Register → Deploy"]

    style B fill:#2563eb,color:#fff,stroke:#1d4ed8
    style C fill:#7c3aed,color:#fff,stroke:#6d28d9
    style D fill:#7c3aed,color:#fff,stroke:#6d28d9
    style E fill:#7c3aed,color:#fff,stroke:#6d28d9
    style F fill:#7c3aed,color:#fff,stroke:#6d28d9
    style G fill:#7c3aed,color:#fff,stroke:#6d28d9

Implementación

Pipeline YAML

# ml-productionize.yaml
name: ml-productionize
steps:
  - name: extract
    agent: build
    task: >
      Parsea experiment.ipynb (formato nbformat JSON).
      Identifica: imports, data loading, preprocessing,
      model definition, training loop, evaluation metrics.
      Ignora: exploratory cells, visualizations, markdown.
      Escribe un resumen en EXTRACTION_PLAN.md.

  - name: structure
    agent: build
    task: >
      Siguiendo EXTRACTION_PLAN.md, genera módulos Python:
      - src/data/loader.py (data loading + preprocessing)
      - src/models/model.py (model definition)
      - src/training/train.py (training loop con MLflow tracking)
      - src/evaluation/evaluate.py (metrics + evaluation)
      - configs/default.yaml (hyperparams externalizados)

  - name: harden
    agent: build
    task: >
      Añade a todos los módulos generados:
      - Type hints en todas las funciones
      - Docstrings Google-style
      - Logging con structlog (reemplaza prints)
      - Error handling (try/except con mensajes útiles)
      - Seed reproducibility (torch/numpy/random)
      Externaliza TODO hyperparameter a configs/default.yaml.

  - name: test
    agent: build
    task: >
      Genera tests/test_data.py, tests/test_model.py, tests/test_training.py.
      Los tests deben verificar: shapes de datos, forward pass del modelo,
      que el training loop reduce loss en 5 steps.
      Ejecuta pytest para verificar que todos pasan.

  - name: pipeline-config
    agent: build
    task: >
      Genera configs/mlflow_pipeline.yaml con la configuración
      para ejecutar el training como job de MLflow:
      entry_points, parameters, metrics, artifacts.
      Genera también un Makefile con targets: train, evaluate, test.

.architect.md para ML

# ML Code Conventions

## Estructura
- src/data/ → data loading, preprocessing, feature engineering
- src/models/ → model definitions
- src/training/ → training loops, callbacks
- src/evaluation/ → metrics, evaluation logic
- configs/ → hydra/omegaconf configs
- tests/ → pytest tests

## Obligatorio
- Type hints en todas las funciones públicas
- Docstrings Google-style con Args/Returns/Raises
- Logging con structlog (no print)
- Configs externalizadas (no hardcoded hyperparams)
- Seed reproducibility (torch.manual_seed, np.random.seed)
- MLflow tracking en training loop (log_params, log_metrics, log_model)

## Prohibido
- No imports con * (from x import *)
- No paths absolutos
- No credenciales en código
- No dependencias sin versión fija en requirements.txt
- No globals mutables

Configuración

# .architect.yaml
llm:
  model: openai/gpt-4.1
  api_key_env: OPENAI_API_KEY

guardrails:
  protected_files:
    - "experiment.ipynb"   # No modificar el notebook original
    - "data/**"            # No tocar datos
    - "*.csv"
    - "*.parquet"
  code_rules:
    - pattern: 'from .* import \*'
      message: "No wildcard imports"
      severity: block
    - pattern: 'print\('
      message: "Usa structlog en vez de print"
      severity: warn

Features de architect usadas

FeatureRol en esta arquitectura
Pipeline5 pasos secuenciales: extract → structure → harden → test → config
Sub-agentsDiferentes agentes para generación vs testing
.architect.mdConvenciones ML del equipo (estructura, logging, configs)
GuardrailsProtege notebook original y datos
code_rulesBloquea wildcards imports, warns en prints
ReportsDocumentación de qué se generó y resultados de tests

Resultado

De un notebook de 200 celdas, architect genera:

  • 4-6 módulos Python limpios con type hints y docstrings
  • Tests unitarios que verifican shapes, forward pass, y convergencia
  • Config YAML con hyperparams externalizados
  • Pipeline config para MLflow/Kubeflow
  • Makefile con targets estándar

El ML Engineer revisa el PR y lo conecta al pipeline MLOps existente. El gap de “semanas de productización” se reduce a “horas de review”.