Hook 机制分析
概述
本文档分析 Spring AI Alibaba Agent Framework 中的 Hook(钩子)机制,包罗 Hook 接口、AgentHook、ModelHook 的筹划、实现原理、实行位置、跳转机制以及详细实现类。
入口类分析
Hook - 钩子接口
Hook 是全部钩子的基接口,界说了钩子的根本本领。
焦点职责:
- 界说钩子名称
- 界说钩子范例
- 界说实行位置
- 界说跳转本领
关键代码:- public interface Hook {
- String getName();
- HookType getHookType();
- List<JumpTo> canJumpTo();
- /**
- * Get the positions where this hook should be executed.
- * By default, this method checks for the @HookPositions annotation on the implementing class.
- *
- * @return array of HookPosition values
- */
- default HookPosition[] getHookPositions() {
- HookPositions annotation = this.getClass().getAnnotation(HookPositions.class);
- if (annotation != null) {
- return annotation.value();
- }
- // Default fallback based on hook type
- if (this instanceof AgentHook) {
- return new HookPosition[]{HookPosition.BEFORE_AGENT, HookPosition.AFTER_AGENT};
- } else if (this instanceof ModelHook) {
- return new HookPosition[]{HookPosition.BEFORE_MODEL, HookPosition.AFTER_MODEL};
- }
- return new HookPosition[0];
- }
- }
复制代码 HookPosition - 实行位置
HookPosition 罗列界说了钩子的实行位置。
关键代码:- public enum HookPosition {
- /**
- * Hook executes before the agent starts processing
- */
- BEFORE_AGENT,
- /**
- * Hook executes after the agent completes processing
- */
- AFTER_AGENT,
- /**
- * Hook executes before the model is called
- */
- BEFORE_MODEL,
- /**
- * Hook executes after the model returns a response
- */
- AFTER_MODEL
- }
复制代码 AgentHook - Agent 级别钩子
AgentHook 在 Agent 实行前后插入逻辑。
关键代码:- public interface AgentHook extends Hook {
- default CompletableFuture<Map<String, Object>> beforeAgent(OverAllState state, RunnableConfig config) {
- return CompletableFuture.completedFuture(Map.of());
- }
- default CompletableFuture<Map<String, Object>> afterAgent(OverAllState state, RunnableConfig config) {
- return CompletableFuture.completedFuture(Map.of());
- }
- }
复制代码 ModelHook - 模子级别钩子
ModelHook 在模子调用前后插入逻辑。
关键代码:- public interface ModelHook extends Hook {
- default CompletableFuture<Map<String, Object>> beforeModel(OverAllState state, RunnableConfig config) {
- return CompletableFuture.completedFuture(Map.of());
- }
- default CompletableFuture<Map<String, Object>> afterModel(OverAllState state, RunnableConfig config) {
- return CompletableFuture.completedFuture(Map.of());
- }
- @Override
- default HookType getHookType() {
- return HookType.MODEL;
- }
- }
复制代码 JumpTo - 跳转目标
JumpTo 罗列界说了钩子可以跳转的目标。
关键代码:- public enum JumpTo {
- tool,
- model,
- end
- }
复制代码 Hook 集成机制
Graph 集成
Hook 被集成到 ReactAgent 的 Graph 中:
关键代码:- // Add hook nodes
- for (Hook hook : hooks) {
- if (hook instanceof AgentHook agentHook) {
- graph.addNode(hook.getName() + ".before", agentHook::beforeAgent);
- graph.addNode(hook.getName() + ".after", agentHook::afterAgent);
- } else if (hook instanceof ModelHook modelHook) {
- graph.addNode(hook.getName() + ".beforeModel", modelHook::beforeModel);
- if (modelHook instanceof HumanInTheLoopHook humanInTheLoopHook) {
- graph.addNode(hook.getName() + ".afterModel", humanInTheLoopHook);
- } else {
- graph.addNode(hook.getName() + ".afterModel", modelHook::afterModel);
- }
- }
- else {
- throw new UnsupportedOperationException("Unsupported hook type: " + hook.getClass().getName());
- }
- }
- // Categorize hooks by position
- List<Hook> beforeAgentHooks = filterHooksByPosition(hooks, HookPosition.BEFORE_AGENT);
- List<Hook> afterAgentHooks = filterHooksByPosition(hooks, HookPosition.AFTER_AGENT);
- List<Hook> beforeModelHooks = filterHooksByPosition(hooks, HookPosition.BEFORE_MODEL);
- List<Hook> afterModelHooks = filterHooksByPosition(hooks, HookPosition.AFTER_MODEL);
- // Determine node flow
- String entryNode = determineEntryNode(beforeAgentHooks, beforeModelHooks);
- String loopEntryNode = determineLoopEntryNode(beforeModelHooks);
- String loopExitNode = determineLoopExitNode(afterModelHooks);
- String exitNode = determineExitNode(afterAgentHooks);
- // Set up edges
- graph.addEdge(START, entryNode);
- setupHookEdges(graph, beforeAgentHooks, afterAgentHooks, beforeModelHooks, afterModelHooks,
- entryNode, loopEntryNode, loopExitNode, exitNode, true, this);
- return graph;
复制代码 工具注入机制
Hook 可以通过 ToolInjection 接口注入工具:
关键代码:- private void setupToolsForHooks(List<Hook> hooks, AgentToolNode toolNode) {
- if (hooks == null || hooks.isEmpty() || toolNode == null) {
- return;
- }
- List<ToolCallback> availableTools = toolNode.getToolCallbacks();
- if (availableTools == null || availableTools.isEmpty()) {
- return;
- }
- for (Hook hook : hooks) {
- if (hook instanceof ToolInjection) {
- ToolInjection toolInjection = (ToolInjection) hook;
- ToolCallback toolToInject = findToolForHook(toolInjection, availableTools);
- if (toolToInject != null) {
- toolInjection.injectTool(toolToInject);
- }
- }
- }
- }
复制代码 详细实现
ModelCallLimitHook - 模子调用限定钩子
ModelCallLimitHook 限定模子调用次数,防止过分调用。
关键代码:- @HookPositions({HookPosition.BEFORE_MODEL, HookPosition.AFTER_MODEL})
- public class ModelCallLimitHook implements ModelHook {
- private static final String THREAD_COUNT_KEY = "__model_call_limit_thread_count__";
- private static final String RUN_COUNT_KEY = "__model_call_limit_run_count__";
- private final Integer threadLimit;
- private final Integer runLimit;
- private final ExitBehavior exitBehavior;
- @Override
- public CompletableFuture<Map<String, Object>> beforeModel(OverAllState state, RunnableConfig config) {
- // Read current counts from state
- int threadModelCallCount = state.value(THREAD_COUNT_KEY, Integer.class).orElse(0);
- int runModelCallCount = state.value(RUN_COUNT_KEY, Integer.class).orElse(0);
- // Check if limits are already exceeded (before making the call)
- boolean threadLimitExceeded = threadLimit != null && threadModelCallCount >= threadLimit;
- boolean runLimitExceeded = runLimit != null && runModelCallCount >= runLimit;
- if (threadLimitExceeded || runLimitExceeded) {
- if (exitBehavior == ExitBehavior.ERROR) {
- throw new ModelCallLimitExceededException(...);
- }
- else if (exitBehavior == ExitBehavior.END) {
- // Add message indicating limit was exceeded and jump to end
- String message = buildLimitExceededMessage(...);
- List<Message> messages = new ArrayList<>((List<Message>) state.value("messages")
- .orElse(new ArrayList<>()));
- messages.add(new AssistantMessage(message));
- Map<String, Object> updates = new HashMap<>();
- updates.put("messages", messages);
- return CompletableFuture.completedFuture(updates);
- }
- }
- return CompletableFuture.completedFuture(Map.of());
- }
- @Override
- public CompletableFuture<Map<String, Object>> afterModel(OverAllState state, RunnableConfig config) {
- // Read current counts from state
- int threadModelCallCount = state.value(THREAD_COUNT_KEY, Integer.class).orElse(0);
- int runModelCallCount = state.value(RUN_COUNT_KEY, Integer.class).orElse(0);
- // Increment counters after the model call
- Map<String, Object> updates = new HashMap<>();
- updates.put(THREAD_COUNT_KEY, threadModelCallCount + 1);
- updates.put(RUN_COUNT_KEY, runModelCallCount + 1);
- return CompletableFuture.completedFuture(updates);
- }
复制代码 功能:
- 跟踪线程级别和运行级别的模子调用次数
- 到达限定时停止 Agent 或抛出非常
- 支持跳转到 END
HumanInTheLoopHook
HumanInTheLoopHook 实现交互机制,答应人工干预 Agent 实行。
功能:
- 在模子调用后停息实行
- 期待人工输入或确认
- 根据人工反馈决定继承或停止
PIIDetectionHook - PII 检测钩子
PIIDetectionHook 检测和处理处罚个人身份信息(PII)。
功能:
- 检测消息中的 PII
- 标志或过滤敏感信息
- 掩护用户隐私
关键类关系
以下 PlantUML 类图展示了 Hook 体系的类关系:
关键流程
以下 PlantUML 时序图展示了 Hook 的实行流程:
实现关键点分析
1. Graph 节点集成
Hook 被转换为 Graph 节点:
- 每个 Hook 方法对应一个节点
- 节点名称格式:{hookName}.{methodName}
- 通过边毗连形成实行链
2. 位置分类
Hook 按位置分类:
- BEFORE_AGENT:Agent 实行前
- AFTER_AGENT:Agent 实行后
- BEFORE_MODEL:模子调用前
- AFTER_MODEL:模子调用后
3. 链式实行
Hook 按序次链式实行:
- beforeAgent hooks 按序次实行
- beforeModel hooks 按序次实行
- afterModel hooks 按逆序实行
- afterAgent hooks 按逆序实行
4. 跳转机制
Hook 可以通过 canJumpTo() 界说跳转本领:
- JumpTo.tool:跳转到工具节点
- JumpTo.model:跳转到模子节点
- JumpTo.end:跳转到竣事节点
跳转通过状态中的 jump_to 键控制。
5. 工具注入
Hook 可以通过 ToolInjection 接口注入工具:
- 在 Graph 初始化时自动注入
- 支持按名称或范例匹配
- 用于 Hook 内部功能实现
6. 状态更新
Hook 通过返回 Map 更新状态:
- 返回的 Map 会归并到当前状态
- 支持键计谋控制更新方式
- 可以修改消息、添加元数据等
总结分析
焦点筹划理念
- 生命周期钩子:在 Agent 和 Model 的关键生命周期点插入逻辑
- Graph 集成:Hook 作为 Graph 节点集成到实行流程
- 跳转控制:支持机动的流程控制,可以跳转到差别节点
- 工具注入:支持 Hook 使用工具实现复杂功能
关键上风
- 机动性:可以在多个位置插入自界说逻辑
- 可扩展性:易于添加新的 Hook 实现
- 流程控制:支持跳转机制实现复杂流程
- 解耦筹划:Hook 与焦点逻辑解耦
办理的标题
- 监控和限定:通过 ModelCallLimitHook 限定调用次数
- 人工干预:通过 HumanInTheLoopHook 实现人工干预
- 安全检测:通过 PIIDetectionHook 检测敏感信息
- 工具集成:通过 ToolInjection 支持 Hook 使用工具
使用场景
- ModelCallLimitHook:必要限定模子调用次数的场景
- HumanInTheLoopHook:必要人工考核或确认的场景
- PIIDetectionHook:必要掩护用户隐私的场景
- 自界说 Hook:必要扩展 Agent 功能的场景
Hook 机制为 Agent Framework 提供了强盛的扩展本领,使开辟者可以大概在 Agent 生命周期的关键点插入自界说逻辑,实现复杂的业务需求。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |