Hooks de predição
Os hooks permitem observar ou moldar cada decisão que o Laya toma, sem fazer um fork dele.
Eles são a costura de extensão para o que toda implantação real precisa: log de auditoria, censura de
PII antes da inferência, cache, métricas, gating por confiança, overrides de roteamento e o
encaminhamento de uma decisão para um serviço externo. Eles são opt-in: sem hooks configurados, o
comportamento de Agent, Router e ONNXAgent não muda.
Eles não servem apenas para chamadas diretas. Cada runnable de LangChain e LangGraph aceita os mesmos cinco argumentos por chamada, então um hook pode ser anexado a um nó de um grafo em vez de ao agente inteiro.
Esta pasta é a referência completa. Comece aqui, depois mergulhe na página de que você precisa:
| página | o que contém |
|---|---|
| Referência da API | cada classe, campo, parâmetro e padrão |
| Ciclo de vida | exatamente quando cada hook roda, com fluxogramas |
| Erros | hooks_raise, on_error, encadeamento de exceções, matriz de falhas |
| Padrões e antipadrões | o que fazer, o que evitar e por quê |
| Exemplos | receitas para copiar e colar em cada caso de uso |
| Tracing | run_id, correlação de spans, OpenTelemetry |
Início 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?"}})
Um objeto pode implementar qualquer subconjunto dos eventos do 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()])
Hooks também podem ser adicionados depois ou ter escopo limitado a um bloco:
agent.add_hook(tracer) # attach at runtime
with agent.hooks_installed(debug): # installed for the block, removed on exit
agent.system_one(state, questions)
Veja registro em tempo de execução. Para um hook que deve valer em todo lugar sem ser passado por fio em cada chamada, registre-o uma vez com padrões para todo o processo:
from laya import hooks
hooks.set_default_hooks(hooks=[Tracer()])
O modelo mental
Há três ideias.
-
Um hook é um callable ou um objeto. Uma função simples é conveniente para um evento; um objeto é conveniente para vários. Ambos são passados para
hooks=/on_predict_start=/on_predict_end=. -
Todo hook de uma chamada compartilha um único
PredictContextmutável. Ele carrega os estados, as perguntas, os resultados, a decisão de roteamento, o nome do modelo, o uso, os tempos e qualquer erro. Uma chamada pode carregar muitos estados de uma vez (predict_batch), então um hook que pretende cobrir toda decisão precisa iterar sobrectx.statesectx.results;ctx.usageectx.elapsed_mssão totais da chamada. Como o contexto é mutável, um hook pode moldar a chamada, não só observá-la: censurar o estado, reescrever as perguntas, substituir o resultado, ou pular a inferência com uma resposta em cache. -
Há dois escopos. Os hooks de
Agentenvolvem uma passada direta; os hooks deRouterenvolvem o roteamento mais a inferência e também veem o ciclo de vida do modelo (on_route,on_load,on_evict). Isso espelha a divisão entre “run hooks” e “agent hooks” em outros 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
Escopo em resumo
Agent / ONNXAgent |
Router |
|
|---|---|---|
on_predict_start |
sim | sim |
on_predict_end |
sim | sim |
on_error |
sim | sim |
on_route |
não | sim |
on_load |
não | sim |
on_evict |
não | sim |
laya.serve e o servidor MCP chamam Router.predict, então os hooks de Router disparam para eles
automaticamente. Os hooks de Agent disparam sempre que o Router roda um agente anexado ou
construído.
Compatibilidade
- Nenhum hook configurado significa nenhuma mudança de comportamento. O caminho sem hooks tem teste de regressão.
- Todos os parâmetros de hook são argumentos nomeados com padrões, então chamadas existentes continuam funcionando.
laya/hooks.pyé Python puro:import layanão puxa o torch por causa dele.- Os hooks são síncronos por padrão. Um evento
async defpode ser envolvido emAsyncHook, ou passado como um callable async simples, e ele roda até o fim por você. hooks_timeoutlimita um hook lento para que ele não possa travar uma solicitação servida.- Mantenha os hooks rápidos e não bloqueantes; veja erros e
padrões para as consequências no
laya.serve.
Veja também
examples/hooks/: hooks executáveis de auditoria, censura, cache e métricas.tests/test_hooks.py: a especificação de comportamento.tests/test_hooks_api.py: a guarda de estabilidade da API.laya/hooks.py: a implementação.