Desarrollo de páginas web y software a medida en Ecuador

jivsoft@hotmail.com +593 97 876 6762
Publicado: /

Del notebook al producto: llevando tu proyecto de IA a producción

Guía práctica para pasar de prototipo a producción: arquitectura mínima, colas y workers, contratos de API, CI/CD con “eval gates”, manejo de secretos, costos y despliegues seguros. Incluye micro-workflow en n8n y tips para Laravel.

Del notebook al producto: llevando tu proyecto de IA a producción

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-Key y evita duplicados en Jobs.
  • Tiempo y reintentos: timeouts claros; semántica de reintento documentada.
  • Versionado: prefija /v1 y 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.vN con changelog y pruebas.
  • Corpus: colecciones con source, updated_at y trust_level.
  • Embeddings: etiqueta índice con embedder_v y chunker_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”

  1. Build: lint + tests + imagen Docker.
  2. Eval offline: corre tu golden set (post #11) y compara contra baseline.
  3. Gate: bloquea despliegue si no mejora utilidad o rompe seguridad/costo.
  4. Release: migrations, warmup de caches e health checks.
  5. 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 .env por 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_id en 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”

  1. Webhook (CI) → recibe {commit, image_tag}.
  2. HTTP → dispara evaluación offline (golden set).
  3. IF → si win-rate ≥ umbral y costo ≤ baseline → seguir; si no, abortar.
  4. HTTP → despliega imagen en staging; corre health checks.
  5. Manual Approval → canary a 10% y, si métricas ok, 100%.
  6. 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 unique o llaves de negocio) y retryUntil().
  • 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.

  • Producción
  • CI/CD
  • Laravel
  • n8n
  • RAG
  • Costos