Hooks de predição
Os hooks deixam-te observar ou moldar cada decisão que o Laya toma, sem lhe fazer fork.
São o ponto de extensão para aquilo de que qualquer implementação real precisa: registo de
auditoria, censura de PII antes da inferência, colocação em cache, métricas, gating por confiança,
substituições de encaminhamento e encaminhamento de uma decisão para um serviço externo. São
opt-in: sem hooks configurados, o comportamento de Agent, Router e ONNXAgent fica
inalterado.
Não servem só para chamadas diretas. Cada runnable de LangChain e LangGraph aceita os mesmos cinco argumentos por chamada, por isso um hook pode ser ligado a um nó de um grafo em vez de ao agente inteiro.
Esta pasta é a referência completa. Começa aqui e depois aprofunda a página de que precisas:
| página | o que contém |
|---|---|
| Referência da API | todas as classes, campos, parâmetros e valores predefinidos |
| Ciclo de vida | exatamente quando corre cada hook, 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 porquê |
| Exemplos | receitas prontas a copiar para 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()])
Os hooks também podem ser acrescentados mais tarde ou limitados 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)
Vê o registo em runtime. Para um hook que deva aplicar-se em todo o lado sem o passar por todas as chamadas, regista-o uma vez com as predefiniçõ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 invocável ou um objeto. Uma função simples é cómoda para um evento; um objeto é cómodo para vários. Ambos são passados a
hooks=/on_predict_start=/on_predict_end=. -
Todos os hooks de uma chamada partilham um mesmo
PredictContextmutável. Transporta os estados, as perguntas, os resultados, a decisão de encaminhamento, o nome do modelo, o usage, a temporização e qualquer erro. Uma chamada pode transportar muitos estados ao mesmo tempo (predict_batch), por isso um hook que queira cobrir cada decisão tem de iterarctx.statesectx.results;ctx.usageectx.elapsed_mssão totais da chamada. Como o contexto é mutável, um hook pode moldar a chamada, e não apenas observá-la: censurar o estado, reescrever as perguntas, substituir o resultado, ou saltar a inferência com uma resposta em cache. -
Há dois âmbitos. Os hooks de
Agentenvolvem uma passagem direta; os hooks deRouterenvolvem o encaminhamento mais a inferência e também podem ver o ciclo de vida do modelo (on_route,on_load,on_evict). Isto espelha a divisão entre «hooks de execução» e «hooks de agente» de outras 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 num relance
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 |
O laya.serve e o servidor MCP chamam Router.predict, por isso os hooks de Router disparam para
eles automaticamente. Os hooks de Agent disparam sempre que o Router corre um agente ligado ou
construído.
Compatibilidade
- Sem hooks configurados não há alteração de comportamento. O caminho sem configuração está coberto por testes de regressão.
- Todos os parâmetros dos hooks são argumentos de palavra-chave com valores predefinidos, por isso as chamadas existentes continuam a funcionar.
laya/hooks.pyé Python puro:import layanão arrasta a torch por causa dele.- Os hooks são síncronos por predefinição. Um evento
async defpode ser envolvido numAsyncHook, ou passado como um invocável assíncrono simples, e corre até ao fim por ti. hooks_timeoutlimita um hook lento para que não possa bloquear um pedido servido.- Mantém os hooks rápidos e sem bloqueios; vê erros e padrões
para as consequências no
laya.serve.
Ver também
examples/hooks/: hooks de auditoria, censura, cache e métricas prontos a correr.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.