Documentación

Hooks de predicción

Los hooks te permiten observar o dar forma a cada decisión que toma Laya, sin hacer un fork.

Son el punto de extensión para todo lo que necesita un despliegue real: registro de auditoría, censura de PII antes de la inferencia, caché, métricas, gating por confianza, anulaciones de enrutamiento y reenvío de una decisión a un servicio externo. Son opt-in: sin hooks configurados, el comportamiento de Agent, Router y ONNXAgent no cambia.

No son solo para llamadas directas. Cada runnable de LangChain y LangGraph recibe los mismos cinco argumentos por llamada, así que puedes adjuntar un hook a un nodo de un grafo en lugar de a todo el agente.

Esta carpeta es la referencia completa. Empieza aquí y luego entra en la página que necesites:

página qué contiene
Referencia de la API cada clase, campo, parámetro y valor predeterminado
Ciclo de vida exactamente cuándo se ejecuta cada hook, con diagramas de flujo
Errores hooks_raise, on_error, encadenamiento de excepciones, matriz de fallos
Patrones y antipatrones qué hacer, qué evitar y por qué
Ejemplos recetas para copiar y pegar en cada caso de uso
Trazado run_id, correlación de spans, OpenTelemetry

Inicio rápido

import laya

def log(ctx):
    print(ctx.model, ctx.results[0]["answers"], ctx.elapsed_ms)

agent = laya.load("convaiinnovations/laya", on_predict_end=log)
agent.system_one("I was charged twice.", {"urgent": {"type": "noul", "instructions": "Urgent?"}})

Un objeto puede implementar cualquier subconjunto de los eventos del ciclo de vida:

class Audit:
    def on_predict_start(self, ctx):
        print("start", ctx.run_id)

    def on_predict_end(self, ctx):
        print("end", ctx.run_id, ctx.usage, ctx.elapsed_ms)

    def on_error(self, ctx):
        print("failed", ctx.run_id, ctx.error)

laya.load("convaiinnovations/laya", hooks=[Audit()])

También puedes agregar hooks más tarde o acotarlos a un bloque:

agent.add_hook(tracer)               # attach at runtime
with agent.hooks_installed(debug):   # installed for the block, removed on exit
    agent.system_one(state, questions)

Consulta el registro en runtime. Para un hook que deba aplicarse en todas partes sin pasarlo por cada llamada, regístralo una vez con los predeterminados para todo el proceso:

from laya import hooks

hooks.set_default_hooks(hooks=[Tracer()])

El modelo mental

Hay tres ideas.

  1. Un hook es un invocable o un objeto. Una función simple resulta cómoda para un evento; un objeto lo es para varios. Ambos se pasan a hooks= / on_predict_start= / on_predict_end=.

  2. Todos los hooks de una llamada comparten un mismo PredictContext mutable. Lleva los estados, las preguntas, los resultados, la decisión de enrutamiento, el nombre del modelo, el uso, los tiempos y cualquier error. Una llamada puede llevar muchos estados a la vez (predict_batch), así que un hook que quiera cubrir cada decisión tiene que iterar ctx.states y ctx.results; ctx.usage y ctx.elapsed_ms son totales de la llamada. Como el contexto es mutable, un hook puede dar forma a la llamada, no solo observarla: censurar el estado, reescribir las preguntas, reemplazar el resultado u omitir la inferencia con una respuesta en caché.

  3. Hay dos ámbitos. Los hooks de Agent envuelven una pasada hacia adelante; los hooks de Router envuelven el enrutamiento más la inferencia y también pueden ver el ciclo de vida del modelo (on_route, on_load, on_evict). Esto refleja la división entre «hooks de ejecución» y «hooks de agente» que usan otros frameworks de agentes.

                             Router.predict(state, questions)
   ┌──────────────────────────────────────────────────────────────────────────┐
   │  route()                                                                 │
   │    ├─ detect language / workflow                                         │
   │    └─ on_route          ctx.decision  (a hook may replace it)            │
   │                                                                          │
   │  load(decision.model)                                                    │
   │    ├─ build checkpoint on first use ──► on_load    ctx.model, ctx.agent  │
   │    └─ evict LRU checkpoint ───────────► on_evict   ctx.model             │
   │                                                                          │
   │  on_predict_start       ctx.states, ctx.questions, ctx.decision          │
   │    │                                                                     │
   │    ├── ctx.skip(results)? ──► skip the forward pass                      │
   │    │                                                                     │
   │    └── Agent.system_one(...)  ──►  Agent-level hooks run here            │
   │           on_predict_start  ─►  forward  ─►  on_predict_end              │
   │                                                                          │
   │  result["routing"] = decision                                            │
   │  on_predict_end         ctx.results, ctx.usage, ctx.elapsed_ms           │
   └──────────────────────────────────────────────────────────────────────────┘
                 any failure on the way ──► on_error, then on_predict_end

Ámbito de un vistazo

Agent / ONNXAgent Router
on_predict_start sí sí
on_predict_end sí sí
on_error sí sí
on_route no sí
on_load no sí
on_evict no sí

laya.serve y el servidor MCP llaman a Router.predict, así que los hooks de Router se disparan para ellos automáticamente. Los hooks de Agent se disparan siempre que el Router ejecuta un agente adjunto o construido.

Compatibilidad

  • Sin hooks configurados no hay cambio de comportamiento. La ruta sin configurar está cubierta por pruebas de regresión.
  • Todos los parámetros de los hooks son argumentos de palabra clave con valores predeterminados, así que las llamadas existentes siguen funcionando.
  • laya/hooks.py es Python puro: import laya no arrastra torch gracias a ello.
  • Los hooks son síncronos de forma predeterminada. Un evento async def se puede envolver en AsyncHook, o pasar como un invocable asíncrono simple, y se ejecuta hasta el final por ti.
  • hooks_timeout limita un hook lento para que no pueda colgar una solicitud servida.
  • Mantén los hooks rápidos y sin bloqueos; consulta errores y patrones para ver las consecuencias en laya.serve.

Ver también