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.
-
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=. -
Todos los hooks de una llamada comparten un mismo
PredictContextmutable. 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 iterarctx.statesyctx.results;ctx.usageyctx.elapsed_msson 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é. -
Hay dos ámbitos. Los hooks de
Agentenvuelven una pasada hacia adelante; los hooks deRouterenvuelven 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.pyes Python puro:import layano arrastra torch gracias a ello.- Los hooks son síncronos de forma predeterminada. Un evento
async defse puede envolver enAsyncHook, o pasar como un invocable asíncrono simple, y se ejecuta hasta el final por ti. hooks_timeoutlimita 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
examples/hooks/: hooks de auditoría, censura, caché y métricas listos para ejecutar.tests/test_hooks.py: la especificación de comportamiento.tests/test_hooks_api.py: la salvaguarda de estabilidad de la API.laya/hooks.py: la implementación.