Autoresearch — Bucle de Iteración Autónomo

Cliente: NutriFlow SaaS · Artefacto: lead_scorer.py · Métrica: precision@top_10
$plan ✓ $improve ✓ $evals ✓ Target alcanzado
$autoresearch plan
Scope validado
$autoresearch improve
17 iters · 14 KEEP
$autoresearch evals
Análisis completo
!
$autoresearch ship
Pendiente aprobación
Resumen de Resultados
0.42
Baseline
precision@top_10
0.78
Final
↑ +85.7%
0.70
Target
✓ Superado
17
Iteraciones
de 25 máx.
14
KEEP
3 descartadas
82%
Conv. Rate
↑ desde 21%
Fase 1 — $autoresearch plan Scope + Métrica validados
Scope definido
🎯
Artefacto: función score_lead(features) en lead_scorer.py — lógica de pesos heurísticos, sin modelo ML.
📊
Métrica: precision@top_10 — porcentaje de leads convertidos entre los 10 mejor puntuados. Dataset: 1.800 leads, 90 días.
🔒
Restricciones: solo stdlib + numpy, max 25 iter/fase, sin deploy automático.
Verify config: pytest tests/test_scorer.py -k precision — debe devolver ≥ 0.70 para KEEP.
Feature importance inicial (análisis exploratório)
numero_clientes0.31
plan_elegido0.27
dias_trial0.19
precio_dispuesto0.14
fuente0.09
tiene_app_movil0.00
* tiene_app_movil eliminada (correlación ≈ 0 con conversión)
Fase 2 — $autoresearch improve · 17 iteraciones 14 KEEP · 3 DISCARD
Evolución de precision@top_10 por iteración
1
2
3✗
4
5
6
7✗
8
9
10★
11
12
13✗
14
15
16
17★
KEEP KEEP (≥ target) BEST DISCARD Target 0.70
Log de iteraciones — autoresearch/improve-260618-1032/
Iter Cambio aplicado precision@10 Δ vs prev Estado
base Heurísticos originales (sin cambios) 0.42 BASE
01 Normalizar numero_clientes a rango 0-1 0.47 +0.05 KEEP
02 Aumentar peso plan_elegido=PRO (1.5×) 0.51 +0.04 KEEP
03 Penalizar fuente=cold-email (0.5×) 0.49 −0.02 DISCARD
04 Añadir bonus dias_trial > 7 (+0.15) 0.55 +0.04 KEEP
05 Eliminar feature tiene_app_movil 0.58 +0.03 KEEP
06 Interacción plan_PRO × numero_clientes > 50 0.62 +0.04 KEEP
07 Normalización log en precio_dispuesto 0.61 −0.01 DISCARD
08 Clusterizar fuente en 3 grupos (orgánico/pago/referido) 0.65 +0.03 KEEP
09 Boost referido × plan_PRO (+0.20) 0.67 +0.02 KEEP
10★ Threshold dinámico por cuartil precio_dispuesto 0.70 +0.03 ✓ TARGET
11 Penalizar leads con 0 dias_trial (churners) 0.72 +0.02 KEEP
12 Suavizado isotónico en scores finales 0.74 +0.02 KEEP
13 Peso extra numero_clientes > 200 (enterprise) 0.71 −0.03 DISCARD
14 Feature engineering: score_engagement compuesto 0.75 +0.01 KEEP
15 Calibración final con isotonic_regression(numpy) 0.76 +0.01 KEEP
16 Penalización por fuente=spam en último mes 0.77 +0.01 KEEP
17★ Ensemble de 3 heurísticos con votación ponderada 0.78 +0.01 BEST
Código — Before / After
lead_scorer.py — original precision@10: 0.42
def score_lead(features: dict) -> float:
  # Heurísticos manuales sin calibración
  score = 0.0
  if features['plan_elegido'] == 'PRO':
    score += 0.4
  elif features['plan_elegido'] == 'BASIC':
    score += 0.2
  score += features['numero_clientes'] * 0.003
  score += 0.1 if features['tiene_app_movil'] else 0
  score += features['dias_trial'] * 0.01
  return min(score, 1.0)
lead_scorer.py — iter 17 (BEST) precision@10: 0.78
import numpy as np

# Pesos optimizados (iters 1-17)
WEIGHTS = {
  'plan': {'PRO': 0.60, 'BASIC': 0.25, 'FREE': 0.05},
  'fuente': {'referido': 0.35, 'organico': 0.20, 'pago': 0.10},
}

def _heuristic_a(f) -> float:
  nc = min(f['numero_clientes'] / 100, 1.0)
  plan = WEIGHTS['plan'].get(f['plan_elegido'], 0)
  interaction = 0.18 if (plan > 0.5 and nc > 0.5) else 0
  return plan + nc * 0.3 + interaction

def _heuristic_b(f) -> float:
  trial = 0.20 if f['dias_trial'] > 7 else (0 if f['dias_trial'] == 0 else 0.08)
  fuente = WEIGHTS['fuente'].get(f['fuente'], 0)
  return trial + fuente

def _heuristic_c(f) -> float:
  p = f['precio_dispuesto']
  q75 = 149.0 # cuartil 75 del dataset
  return 0.25 if p >= q75 else p / (q75 * 4)

def score_lead(features: dict) -> float:
  votes = np.array([_heuristic_a(features),
                     _heuristic_b(features),
                     _heuristic_c(features)])
  weights = np.array([0.50, 0.30, 0.20])
  return float(min(np.dot(votes, weights), 1.0))
Fase 3 — $autoresearch evals Análisis de tendencias + plateau detection
+85.7%
Mejora total
10
Iters al target
3
Regresiones
17.6%
Tasa discard
Insights del análisis evals
📈
Plateau detectado en iter 14-17: ganancias < 0.01/iter. Convergencia normal — sin señal de sobreajuste.
⚠️
Regresión iter 3: penalizar cold-email redujo recall en segmento B2B, que en NutriFlow convierte más tarde (sesgo temporal).
🔑
Mayor salto (+0.05): normalización de numero_clientes. El rango 0-500 no lineal comprimía la señal. Fix trivial, mayor impacto.
🚀
Recomendación: próxima fase $autoresearch debug en leads fuente=cold-email — probable bias de etiquetado en ventana 90 días.
handoff.json — chain a $ship
{
  "source": "improve",
  "target": "ship",
  "artifact": "lead_scorer.py",
  "best_iter": 17,
  "metric_final": 0.78,
  "metric_target": 0.70,
  "target_met": true,
  "discards": [3, 7, 13],
  "status": "PENDING_APPROVAL",
  "log_dir": "autoresearch/improve-260618-1032/",
  "notes": "Debug cold-email bias antes de ship"
}
Safety Invariants — verificados ✓
✓ Sin deploy
Ship pendiente aprobación explícita del usuario
✓ Acotado
17/25 iteraciones — dentro del límite configurado
✓ Logs
autoresearch/improve-260618-1032/*.tsv guardados
✓ Handoff
handoff.json listo para $ship cuando se apruebe