文件導航

預測鉤子

鉤子讓你觀察或塑造 Laya 做出的每一個決策,而無需 fork 它。

它們是每個真實部署都需要的東西的擴充套件縫:審計日誌、推理前脫敏 PII、快取、指標、置信度門控、 路由覆蓋,以及把決策轉發給外部服務。它們是選用的:不配置任何鉤子時,Agent、Router 和 ONNXAgent 的行為不變。

它們不只用於直接呼叫。每個 LangChain 與 LangGraph runnable 都接受同樣五個逐呼叫 參數,所以鉤子可以掛到圖裡的某一個節點上,而不是整個智慧體上。

這個資料夾是完整的參考。從這裡開始,然後深入你需要的那一頁:

頁面 裡面有什麼
API 參考 每一個類、欄位、參數和預設值
生命週期 每個鉤子究竟何時執行,帶流程圖
錯誤 hooks_raise、on_error、異常鏈、失敗矩陣
模式與反模式 該做什麼、該避免什麼,以及為什麼
示例 每個用例都可複製貼上的配方
鏈路追蹤 run_id、span 關聯、OpenTelemetry

快速開始

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?"}})

一個物件可以實現生命週期事件中的任意子集:

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()])

鉤子也可以在之後新增,或者限定在一段程式碼塊內:

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

見執行時註冊。對於一個應該處處生效、又不想穿過每次呼叫的 鉤子,用程序級預設值註冊一次:

from laya import hooks

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

心智模型

有三個概念。

  1. 鉤子是一個可呼叫物件或一個物件。 一個普通函式適合一個事件;一個物件適合多個。兩者都傳給 hooks= / on_predict_start= / on_predict_end=。

  2. 一次呼叫的每個鉤子共享同一個可變的 PredictContext。 它攜帶狀態、問題、結果、路由決策、 模型名、usage、計時和任何錯誤。一次呼叫可以同時攜帶很多狀態(predict_batch),所以一個想 覆蓋每一個決策的鉤子必須遍歷 ctx.states 和 ctx.results;ctx.usage 和 ctx.elapsed_ms 是整次呼叫的合計。因為上下文是可變的,鉤子可以塑造這次呼叫,而不只是旁觀:脫敏狀態、改寫 問題、替換結果,或用快取答案跳過推理。

  3. 有兩個作用域。 Agent 鉤子包住一次前向傳播;Router 鉤子包住路由加推理,還能看到模型 生命週期(on_route、on_load、on_evict)。這對應其他智慧體框架裡「run hooks」與 「agent hooks」的區分。

                             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

作用域一覽

Agent / ONNXAgent Router
on_predict_start 是 是
on_predict_end 是 是
on_error 是 是
on_route 否 是
on_load 否 是
on_evict 否 是

laya.serve 和 MCP 伺服器呼叫 Router.predict,所以 Router 鉤子對它們自動生效。Router 執行一個 掛載的或內建的 agent 時,Agent 鉤子就生效。

相容性

  • 不配置鉤子就沒有任何行為變化。未設定的路徑有迴歸測試。
  • 所有鉤子參數都是帶預設值的關鍵字參數,所以現有的呼叫繼續可用。
  • laya/hooks.py 是純 Python:import laya 不會因為它而拉進 torch。
  • 鉤子預設是同步的。一個 async def 事件可以包進 AsyncHook,或者 作為一個普通的非同步可呼叫物件傳入,它會替你執行到完成。
  • hooks_timeout 給慢鉤子設上界,使它無法掛起一個正在服務的請求。
  • 保持鉤子快且非阻塞;關於對 laya.serve 的後果見錯誤和 模式。

另見