Inteligencia Artificial · Serie LLMs y n8n
Del notebook al producto: llevando tu proyecto de IA a producción
Un buen prototipo impresiona; un buen producto no se cae, es auditable y cuesta lo que debe. Aquí tienes un plan directo para convertir tus notebooks en un servicio real.
En el post anterior cerramos el ciclo de mejora con feedback humano. Ahora toca hacerlo operable: arquitectura mínima, contratos de API, colas, CI/CD y control de costos.
Arquitectura mínima de producción
- API Laravel: endpoints y auth (tokens/keys, rate limit, scopes).
- Queue/Workers: Jobs para llamadas LLM, RAG, evaluaciones y post-proceso.
- Vector Store: embeddings + metadatos versionados.
- LLM provider: uno principal y uno de fallback con políticas de conmutación.
- n8n: orquestaciones externas (webhooks, ETL semántico, alertas).
- Observabilidad: logs estructurados, métricas y trazas (ver post #20).
- Secrets: gestor de secretos (variables de entorno, vault) y rotación.
Contratos de API (sin sorpresas)
- Entrada: valida tipos, límites y enums; rechaza extras.
- Salida: JSON estricto con
{"request_id": "...", "status": "...", "data": {...}}. - Idempotencia: acepta
Idempotency-Keyy evita duplicados en Jobs. - Tiempo y reintentos: timeouts claros; semántica de reintento documentada.
- Versionado: prefija
/v1y publica schemas/OpenAPI.
// routes/api.php
Route::post('/v1/qa', QaController::class)->middleware(['auth:api','throttle:60,1']);
// app/Http/Controllers/QaController.php (esqueleto)
public function __invoke(QaRequest $req) {
$rid = Str::uuid()->toString();
dispatch(new QaJob($rid, $req->validated()))->onQueue('llm');
return response()->json(['request_id'=>$rid,'status'=>'queued']);
}
Colas y workers (tu mejor seguro)
- Separa colas:
llm,rag,eval,webhooks. - Backoff exponencial y max attempts; registra causa raíz.
- Dead Letter queue para análisis y replays controlados.
- Presupuestos: tokens/tiempo por job; circuit breaker por proveedor.
// app/Jobs/QaJob.php (fragmento)
public function handle(LLM $llm, Retriever $retriever) {
$ctx = $retriever->topK($this->query, topK:3, filters: $this->filters);
$res = $llm->answerWithCitations($this->query, $ctx, budgetTokens: 1200);
event(new QaCompleted($this->requestId, $res));
}
Versiona lo que importa (prompts, datos, embeddings)
- Prompts:
prompt.vNcon changelog y pruebas. - Corpus: colecciones con
source,updated_atytrust_level. - Embeddings: etiqueta índice con
embedder_vychunker_v. - Pipelines:
pipeline.vN(modelo, prompt, topK, reranker).
// Ejemplo de tabla
pipelines(id, name, model, prompt_v, embedder_v, chunker_v, top_k, created_at)
CI/CD con “eval gates”
- Build: lint + tests + imagen Docker.
- Eval offline: corre tu golden set (post #11) y compara contra baseline.
- Gate: bloquea despliegue si no mejora utilidad o rompe seguridad/costo.
- Release: migrations, warmup de caches e health checks.
- Rollout: canary/blue-green + feature flags.
# pseudo Makefile
make test && make build && make eval && make deploy
# si "make eval" < baseline => exit 1
Cost engineering (sin dolor)
- Model routing: por dificultad/tenant → SLM barato por defecto, LLM grande por excepción.
- Top-K y contexto: menos es más; filtra por metadatos antes de vectorizar/injectar.
- Caching: plantillas y preguntas frecuentes (TTL + keys por idioma/tenant).
- Alertas: costo p95 por endpoint/tenant; corta picos por rate limit.
Seguridad y secretos
- Variables en
.envpor ambiente; nunca subas claves. - Scopes mínimos para APIs y roles por endpoint.
- PII: redacción al borde; guarda metadatos, no texto crudo cuando puedas.
- Guardrails de salida (post #16) y abstención obligatoria cuando falte evidencia.
Observabilidad base (teaser de #20)
- Correlación:
request_iden logs, métricas y trazas. - Métricas: costo por request, p95 por etapa, % JSON válido, groundedness.
- Dashboards: performance, calidad y costos por modelo/tenant.
Estrategia de despliegue
- Canary: 5–10% de tráfico; compara métricas clave.
- Rollback con una orden (imagen anterior + schema compatible).
- Runbook: qué hacer si sube p95 o baja groundedness (ver posts #28 y #25).
Micro-workflow en n8n: “Deploy con eval gate”
- Webhook (CI) → recibe
{commit, image_tag}. - HTTP → dispara evaluación offline (golden set).
- IF → si win-rate ≥ umbral y costo ≤ baseline → seguir; si no, abortar.
- HTTP → despliega imagen en staging; corre health checks.
- Manual Approval → canary a 10% y, si métricas ok, 100%.
- Notifier → reporta métricas y etiqueta
pipeline.vN.prod.
Tips Laravel/PHP
- HTTP Client con timeouts, retry/backoff y
throw()para errores claros. - Jobs idempotentes (usa
uniqueo llaves de negocio) yretryUntil(). - FormRequest para validar contratos; Resources para salidas consistentes.
- Cache por tenant/idioma; rate limiter por API key.
Errores comunes (y cómo evitarlos)
- Hacer todo en una request sin colas → tiempos impredecibles.
- Sin contratos de I/O → salidas frágiles y parsing a mano.
- Desplegar sin eval gate → regresiones silenciosas.
- Logs con PII → riesgo legal y fuga de datos.
- Sin fallback de modelo → degradación total ante caídas del proveedor.
Conclusión
Pasar a producción es estandarizar: contratos, colas, versiones, telemetría y despliegues con barandas. Empieza mínimo, mide, y promueve solo lo que mejora con evidencia.
← Anterior: RAG con feedback humano: mejora continua para tu asistente inteligente