1. 自定义中间件核心概念解析
在LangChain框架中,中间件(Middleware)是扩展智能体行为的关键机制。它允许开发者在智能体执行流程的特定节点插入自定义逻辑,而无需修改核心代码。这种设计模式类似于Web开发中的中间件管道,但针对AI工作流进行了专门优化。
中间件的核心价值在于提供了非侵入式的扩展能力。想象一下,你正在搭建一个AI客服系统,突然需要添加对话日志记录功能。如果没有中间件机制,你可能需要修改每个模型调用点的代码。而通过中间件,你只需要编写一个日志记录模块,然后将其插入执行管道即可。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 钩子类型深度对比
2.1 节点式钩子(Node-style hooks)
节点式钩子就像高速公路上的检查站,在固定的位置对通过的车辆(数据流)进行检查或处理。它们的特点是:
- 执行时机固定:在智能体生命周期的特定阶段触发
- 顺序执行:多个中间件的钩子按注册顺序依次执行
- 无返回值要求:通常用于观测或简单修改上下文
典型应用场景包括:
- 执行日志记录(before/after关键节点)
- 输入输出验证(before_model校验输入格式)
- 执行时间统计(记录各阶段耗时)
2.2 包装式钩子(Wrap-style hooks)
包装式钩子则更像是给核心操作套上的"包装纸",可以完全控制内部操作的执行。它们的特点是:
- 完全控制权:可以修改、跳过甚至替换原始操作
- 必须返回结果:需要返回与原始操作兼容的结果
- 更重的责任:处理不当可能导致流程中断
典型应用场景包括:
- 实现重试机制(网络请求失败时自动重试)
- 结果缓存(避免重复计算相同输入)
- 流量控制(限制并发请求数)
重要选择原则:当只需要观察或简单修改时用节点式钩子;当需要完全控制操作行为时用包装式钩子。
3. 节点式钩子实战详解
3.1 基础实现方式
最简单的中间件可以通过函数装饰器实现。以下是一个完整的执行日志记录中间件示例:
python复制from langchain.agents import AgentExecutor
from typing import Dict, Any
def log_execution_flow(func):
"""记录智能体执行流程的装饰器"""
def wrapper(*args, **kwargs):
agent: AgentExecutor = args[0]
print(f"[LOG] Agent started with inputs: {kwargs['inputs']}")
result = func(*args, **kwargs)
print(f"[LOG] Agent completed with outputs: {result}")
return result
return wrapper
# 使用示例
@log_execution_flow
def run_agent(agent, inputs):
return agent.run(inputs)
3.2 类式中间件实现
对于更复杂的场景,建议使用类形式实现中间件。下面是支持所有节点式钩子的完整类实现:
python复制from typing import Optional, Dict, Any
class MonitoringMiddleware:
"""全面的监控中间件"""
def __init__(self, monitoring_service):
self.service = monitoring_service
def before_agent(self, inputs: Dict[str, Any]):
"""智
