ab_model_routing
Implementa un sistema de routing A/B para evaluar nuevas versiones de modelos de machine learning en producción dentro del pipeline de verificación de identidad. Permite dirigir un porcentaje configurable del tráfico de verificación a un modelo candidato (ej: ArcFace v2) mientras el modelo de control (ej: ArcFace v1) sirve el resto, recopilando métricas comparativas de FAR, FRR y latencia para tomar decisiones de promoción basadas en datos.
When to use
Usa esta skill cuando necesites evaluar una nueva versión de modelo ML en producción dentro del model_server_agent. Aplica cuando se tenga un modelo candidato que haya pasado validación offline pero se requiera confirmar su rendimiento con tráfico real de verificación antes de hacer un rollout completo.
Instructions
Definir la configuración del experimento A/B:
@dataclass
class ABExperiment:
experiment_id: str
model_name: str # ej: "arcface"
control_version: str # ej: "1.0.0"
candidate_version: str # ej: "2.0.0"
traffic_split: float # 0.0 a 1.0, porcentaje al candidato
start_date: datetime
min_samples: int # mínimo de verificaciones para significancia
status: str # "running", "completed", "aborted"
metrics_config: dict # métricas a comparar: ["far", "frr", "latency_p95"]
Implementar el router que asigna cada solicitud de verificación al modelo control o candidato:
class ABRouter:
def __init__(self, experiment: ABExperiment):
self.experiment = experiment
self.control_model = load_model(experiment.control_version)
self.candidate_model = load_model(experiment.candidate_version)
def route(self, session_id: str) -> tuple[str, Model]:
# Hash determinista por session_id para consistencia
hash_value = int(hashlib.sha256(session_id.encode()).hexdigest(), 16)
if (hash_value % 100) / 100 < self.experiment.traffic_split:
return "candidate", self.candidate_model
return "control", self.control_model
Registrar los resultados de cada verificación asociados al grupo (control/candidato):
class ABMetricsCollector:
def record(self, experiment_id: str, group: str, session_id: str,
prediction: dict, ground_truth: dict = None):
self.db.insert({
"experiment_id": experiment_id,
"group": group,
"session_id": session_id,
"similarity_score": prediction["score"],
"is_match": prediction["is_match"],
"latency_ms": prediction["latency_ms"],
"timestamp": datetime.utcnow()
})
Implementar el análisis estadístico para determinar si la diferencia entre modelos es significativa:
from scipy import stats
def analyze_experiment(self, experiment_id: str) -> dict:
control_scores = self.get_scores(experiment_id, "control")
candidate_scores = self.get_scores(experiment_id, "candidate")
t_stat, p_value = stats.ttest_ind(control_scores, candidate_scores)
control_far = self.calculate_far(experiment_id, "control")
candidate_far = self.calculate_far(experiment_id, "candidate")
return {
"p_value": p_value,
"control_far": control_far,
"candidate_far": candidate_far,
"is_significant": p_value < 0.05,
"recommendation": "promote" if candidate_far < control_far and p_value < 0.05 else "keep_control"
}
Configurar guardrails automáticos que detengan el experimento si el modelo candidato degrada métricas críticas:
def check_guardrails(self, experiment_id: str):
candidate_far = self.calculate_far(experiment_id, "candidate")
if candidate_far > 0.001: # FAR > 0.1% -> abortar
self.abort_experiment(experiment_id)
self.alert("AB experiment aborted: candidate FAR exceeded threshold")
Exponer un dashboard o endpoint con métricas en tiempo real del experimento: FAR, FRR, latencia p50/p95, volumen de muestras por grupo y significancia estadística actual.
Al completar el experimento, generar un informe automático y, si el candidato es superior, integrarse con la skill model_versioning para promover la nueva versión.
Notes
- El routing debe ser determinista por
session_id para que todas las llamadas de una misma verificación (embedding, comparación) usen el mismo modelo, evitando inconsistencias en los resultados.
- Comenzar con un traffic split conservador (5-10% al candidato) e incrementar gradualmente solo si los guardrails no se activan; nunca iniciar un experimento con mas del 20% en el candidato sin validación previa.
- Los experimentos A/B en modelos de seguridad KYC requieren un volumen mínimo significativo (recomendado >1000 verificaciones por grupo) antes de tomar decisiones de promoción; resultados prematuros pueden ser engañosos.
1---2name: ab-model-routing3description: Routing A/B entre versiones de modelos ML para evaluar mejoras en producción con métricas FAR/FRR4---56# ab_model_routing78Implementa un sistema de routing A/B para evaluar nuevas versiones de modelos de machine learning en producción dentro del pipeline de verificación de identidad. Permite dirigir un porcentaje configurable del tráfico de verificación a un modelo candidato (ej: ArcFace v2) mientras el modelo de control (ej: ArcFace v1) sirve el resto, recopilando métricas comparativas de FAR, FRR y latencia para tomar decisiones de promoción basadas en datos.910## When to use1112Usa esta skill cuando necesites evaluar una nueva versión de modelo ML en producción dentro del **model_server_agent**. Aplica cuando se tenga un modelo candidato que haya pasado validación offline pero se requiera confirmar su rendimiento con tráfico real de verificación antes de hacer un rollout completo.1314## Instructions15161. Definir la configuración del experimento A/B:1718 ```python19 @dataclass20 class ABExperiment:21 experiment_id: str22 model_name: str # ej: "arcface"23 control_version: str # ej: "1.0.0"24 candidate_version: str # ej: "2.0.0"25 traffic_split: float # 0.0 a 1.0, porcentaje al candidato26 start_date: datetime27 min_samples: int # mínimo de verificaciones para significancia28 status: str # "running", "completed", "aborted"29 metrics_config: dict # métricas a comparar: ["far", "frr", "latency_p95"]30 ```31322. Implementar el router que asigna cada solicitud de verificación al modelo control o candidato:3334 ```python35 class ABRouter:36 def __init__(self, experiment: ABExperiment):37 self.experiment = experiment38 self.control_model = load_model(experiment.control_version)39 self.candidate_model = load_model(experiment.candidate_version)4041 def route(self, session_id: str) -> tuple[str, Model]:42 # Hash determinista por session_id para consistencia43 hash_value = int(hashlib.sha256(session_id.encode()).hexdigest(), 16)44 if (hash_value % 100) / 100 < self.experiment.traffic_split:45 return "candidate", self.candidate_model46 return "control", self.control_model47 ```48493. Registrar los resultados de cada verificación asociados al grupo (control/candidato):5051 ```python52 class ABMetricsCollector:53 def record(self, experiment_id: str, group: str, session_id: str,54 prediction: dict, ground_truth: dict = None):55 self.db.insert({56 "experiment_id": experiment_id,57 "group": group,58 "session_id": session_id,59 "similarity_score": prediction["score"],60 "is_match": prediction["is_match"],61 "latency_ms": prediction["latency_ms"],62 "timestamp": datetime.utcnow()63 })64 ```65664. Implementar el análisis estadístico para determinar si la diferencia entre modelos es significativa:6768 ```python69 from scipy import stats7071 def analyze_experiment(self, experiment_id: str) -> dict:72 control_scores = self.get_scores(experiment_id, "control")73 candidate_scores = self.get_scores(experiment_id, "candidate")7475 t_stat, p_value = stats.ttest_ind(control_scores, candidate_scores)76 control_far = self.calculate_far(experiment_id, "control")77 candidate_far = self.calculate_far(experiment_id, "candidate")7879 return {80 "p_value": p_value,81 "control_far": control_far,82 "candidate_far": candidate_far,83 "is_significant": p_value < 0.05,84 "recommendation": "promote" if candidate_far < control_far and p_value < 0.05 else "keep_control"85 }86 ```87885. Configurar guardrails automáticos que detengan el experimento si el modelo candidato degrada métricas críticas:8990 ```python91 def check_guardrails(self, experiment_id: str):92 candidate_far = self.calculate_far(experiment_id, "candidate")93 if candidate_far > 0.001: # FAR > 0.1% -> abortar94 self.abort_experiment(experiment_id)95 self.alert("AB experiment aborted: candidate FAR exceeded threshold")96 ```97986. Exponer un dashboard o endpoint con métricas en tiempo real del experimento: FAR, FRR, latencia p50/p95, volumen de muestras por grupo y significancia estadística actual.991007. Al completar el experimento, generar un informe automático y, si el candidato es superior, integrarse con la skill `model_versioning` para promover la nueva versión.101102## Notes103104- El routing debe ser determinista por `session_id` para que todas las llamadas de una misma verificación (embedding, comparación) usen el mismo modelo, evitando inconsistencias en los resultados.105- Comenzar con un traffic split conservador (5-10% al candidato) e incrementar gradualmente solo si los guardrails no se activan; nunca iniciar un experimento con mas del 20% en el candidato sin validación previa.106- Los experimentos A/B en modelos de seguridad KYC requieren un volumen mínimo significativo (recomendado >1000 verificaciones por grupo) antes de tomar decisiones de promoción; resultados prematuros pueden ser engañosos.