Dokumentation

Vorhersage-Hooks

Mit Hooks kannst du jede Entscheidung von Laya beobachten oder formen, ohne sie zu forken.

Sie sind die Erweiterungsnaht für alles, was jedes echte Deployment braucht: Audit-Logging, PII-Redaktion vor der Inferenz, Caching, Metriken, Konfidenz-Gating, Routing-Überschreibungen und das Weiterleiten einer Entscheidung an einen externen Dienst. Sie sind opt-in: ohne konfigurierte Hooks bleibt das Verhalten von Agent, Router und ONNXAgent unverändert.

Sie sind nicht nur für direkte Aufrufe gedacht. Jeder Runnable von LangChain und LangGraph nimmt dieselben fünf Argumente pro Aufruf entgegen, sodass du einen Hook an einen einzelnen Knoten in einem Graphen hängen kannst statt an den gesamten Agenten.

Dieser Ordner ist die vollständige Referenz. Beginne hier und tauche dann in die Seite ein, die du brauchst:

Seite Inhalt
API-Referenz jede Klasse, jedes Feld, jeder Parameter und jeder Standardwert
Lebenszyklus wann genau jeder Hook läuft, mit Flussdiagrammen
Fehler hooks_raise, on_error, Verkettung von Ausnahmen, Fehlermatrix
Muster und Anti-Muster was zu tun, was zu vermeiden ist und warum
Beispiele Copy-Paste-Rezepte für jeden Anwendungsfall
Tracing run_id, Span-Korrelation, OpenTelemetry

Schnellstart

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

Ein Objekt kann jede Teilmenge der Lebenszyklus-Ereignisse implementieren:

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 lassen sich auch später hinzufügen oder auf einen Block begrenzen:

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

Siehe Registrierung zur Laufzeit. Für einen Hook, der überall gelten soll, ohne ihn durch jeden Aufruf zu schleusen, registriere ihn einmal mit prozessweiten Standardwerten:

from laya import hooks

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

Das mentale Modell

Es gibt drei Ideen.

  1. Ein Hook ist ein Callable oder ein Objekt. Eine einfache Funktion ist praktisch für ein Ereignis; ein Objekt ist praktisch für mehrere. Beides wird an hooks= / on_predict_start= / on_predict_end= übergeben.

  2. Alle Hooks eines Aufrufs teilen sich ein einziges veränderbares PredictContext. Es trägt die Zustände, Fragen, Ergebnisse, die Routing-Entscheidung, den Modellnamen, die Nutzung, die Zeiten und jeden Fehler. Ein Aufruf kann viele Zustände auf einmal tragen (predict_batch), also muss ein Hook, der jede Entscheidung abdecken will, über ctx.states und ctx.results iterieren; ctx.usage und ctx.elapsed_ms sind Summen für den Aufruf. Weil der Kontext veränderbar ist, kann ein Hook den Aufruf formen, nicht nur beobachten: den Zustand redigieren, die Fragen umschreiben, das Ergebnis ersetzen oder die Inferenz mit einer gecachten Antwort überspringen.

  3. Es gibt zwei Geltungsbereiche. Hooks von Agent umschließen einen Vorwärtsdurchlauf; Hooks von Router umschließen Routing plus Inferenz und sehen zusätzlich den Modell-Lebenszyklus (on_route, on_load, on_evict). Das spiegelt die Trennung zwischen „Run-Hooks“ und „Agent-Hooks“ in anderen Agent-Frameworks wider.

                             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

Umfang auf einen Blick

Agent / ONNXAgent Router
on_predict_start ja ja
on_predict_end ja ja
on_error ja ja
on_route nein ja
on_load nein ja
on_evict nein ja

laya.serve und der MCP-Server rufen Router.predict auf, also werden Router-Hooks für sie automatisch ausgelöst. Agent-Hooks werden ausgelöst, wann immer der Router einen angehängten oder gebauten Agenten ausführt.

Kompatibilität

  • Ohne konfigurierte Hooks gibt es keine Verhaltensänderung. Der Pfad ohne Hooks ist regressionsgetestet.
  • Alle Hook-Parameter sind Keyword-Argumente mit Standardwerten, sodass bestehende Aufrufe weiter funktionieren.
  • laya/hooks.py ist reines Python: import laya zieht deswegen kein torch herein.
  • Hooks sind standardmäßig synchron. Ein async def-Ereignis kann in AsyncHook verpackt oder als einfaches asynchrones Callable übergeben werden, und es läuft für dich bis zum Ende durch.
  • hooks_timeout begrenzt einen langsamen Hook, damit er eine bediente Anfrage nicht aufhängen kann.
  • Halte Hooks schnell und nicht blockierend; siehe Fehler und Muster für die Folgen für laya.serve.

Siehe auch