Skip to content
Embabel 文档版本 0.3.0-SNAPSHOT 源快照 2f4aba1c 更新于 2026-09-29

31 · 回调与拦截器(Interceptors)

工具循环回调(Tool Loop Callbacks)

Embabel 中的 LLM 调用发生在 ToolLoop 内部。 Embabel 的工具循环高度可定制,提供了清晰的扩展点,并把**观察(inspectors)与变换(transformers)**区分开来。

  • Inspectors(检查器) 观察循环,不修改它。实现任一回调即可:

    • beforeLlmCall
    • afterLlmCall
    • afterToolResult
    • afterIteration

    Inspectors 非常适合日志、指标采集、调试,设计上是只读的。

  • Transformers(变换器) 修改流经循环的数据。用它们来截断过大的工具结果、对对话历史施加滑动窗口、脱敏敏感内容。 它们改变的是 LLM 看到的内容。

工具循环回调接口

以下是回调接口(Kotlin 原文):

kotlin
/**
 * Read-only observer for tool loop lifecycle events.
 * Use for logging, metrics, debugging - does not modify state.
 */
interface ToolLoopInspector : ToolLoopCallback {

    /** Called before each LLM invocation. Default no-op. */
    fun beforeLlmCall(context: BeforeLlmCallContext) = Unit

    /** Called after LLM returns a response, before processing tool calls. Default no-op. */
    fun afterLlmCall(context: AfterLlmCallContext) = Unit

    /** Called after each tool produces a result. Default no-op. */
    fun afterToolResult(context: AfterToolResultContext) = Unit

    /** Called after each complete iteration (all tool calls processed). Default no-op. */
    fun afterIteration(context: AfterIterationContext) = Unit
}

/**
 * Transforms message history or tool results during tool loop execution.
 * Use for compression, summarization, windowing.
 */
interface ToolLoopTransformer : ToolLoopCallback {

    /** Transform history before sending to LLM. Return modified list. */
    fun transformBeforeLlmCall(context: BeforeLlmCallContext): List<Message> = context.history

    /** Transform LLM response before adding to history. Return modified message. */
    fun transformAfterLlmCall(context: AfterLlmCallContext): Message = context.response

    /** Transform tool result before adding to history. Return modified string. */
    fun transformAfterToolResult(context: AfterToolResultContext): String = context.resultAsString

    /** Transform history after iteration completes. Return modified list. */
    fun transformAfterIteration(context: AfterIterationContext): List<Message> = context.history
}

开箱即用的简单回调

框架提供了几个开箱即用的简单回调:

  • ToolLoopLoggingInspector —— 在 LLM 调用前后、工具执行之后、以及工具循环每轮迭代之后记录调用详情;
  • ToolResultTruncatingTransformer —— 截断工具调用结果;
  • SlidingWindowTransformer —— 维护消息的滑动窗口以控制上下文大小,同时保留对话上下文的 system message。

用法:工具循环回调

java
// 带工具与回调执行
var result = ai.withDefaultLlm()
        .withTools(tools)
        .withToolLoopInspectors(callbackTracker, loggingInspector)
        .withToolLoopTransformers(truncatingTransformer, slidingWindowTransformer)
        .creating(RestaurantRecommendation.class)
        .fromPrompt("""
                I'm looking for an Italian restaurant near the Upper East Side in NYC.

                You have access to these tools to fetch restaurant menus:
                %s

                Please fetch the menus and recommend the best restaurant for a romantic dinner.
                """.formatted(String.join(", ", toolNames)));

工具调用拦截器(Tool Call Interceptors)

工具循环回调为"观察 LLM 调用、对话历史与工具执行"提供了强大的能力; 但在实践中,也存在对精简版 inspector 回调的需求。

动机:流式模式

流式是事件驱动的。流式模型提供了获取 thinking 块与结构化对象的回调。

框架还提供了另一类流式回调 —— Tool Call 回调。工具调用回调包含工具定义、工具结果以及工具执行耗时的信息。

工具调用接口

kotlin
/**
 * Read-only observer for individual tool call events.
 *
 * Provides observation of tool execution without access to conversation history
 * or iteration state. Works in both streaming mode (where the framework manages
 * the tool loop internally) and non-streaming mode (as a lightweight alternative
 * to [ToolLoopInspector] when history/iteration context is not needed).
 *
 * @see ToolLoopInspector for tool loop-level inspection with full conversation context
 */
interface ToolCallInspector {

    /**
     * Called before tool execution starts.
     * Default no-op.
     */
    fun beforeToolCall(context: BeforeToolCallContext) = Unit

    /**
     * Called after tool execution completes (success or failure).
     * Default no-op.
     */
    fun afterToolCall(context: AfterToolCallContext) = Unit
}

开箱即用的工具调用拦截器

采集工具调用指标请参考 ToolCallLoggingInspector。

用法:工具调用拦截器

java
PromptRunner runner = ai.withDefaultLlm()
        .withToolObject(new Tooling())
        .withToolCallInspectors(new ToolCallLoggingInspector(ToolLoopLoggingInspector.LogLevel.INFO, logger));

工具调用拦截器同时适用于流式与非流式模式。

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。