在构建AI代理系统时,我们常常面临一个关键矛盾:既希望AI能够自主决策和执行任务,又需要对它的行为进行必要的约束和监控。Middleware(中间件)正是解决这一矛盾的完美方案。它就像给AI代理装上了"控制塔",在不影响核心功能的前提下,为系统添加了安全检查、性能监控、错误处理等关键能力。
想象一下,你有一个能干的AI助手,它可以自主思考、决策和执行任务。但如果完全放任它自由行动,可能会遇到以下问题:
Middleware就是为解决这些问题而生的。它通过在AI代理的关键执行节点插入"拦截点",实现了对代理行为的精细控制。这种设计既保留了AI的自主性,又确保了系统的安全性和可靠性。
要理解Middleware如何工作,我们需要先了解LangChain Agent的基本执行流程:
code复制用户请求 → 模型思考 → 决定是否使用工具 → 使用工具 → 观察结果 → 再思考 → 返回结果
Middleware就是在这个循环的各个关键节点上插入监控和控制逻辑。具体来说,它可以在以下6个关键时机进行干预:
| 干预时机 | 触发时刻 | 典型应用场景 |
|---|---|---|
| before_agent | 整个Agent开始运行前 | 加载记忆、验证输入安全性 |
| before_model | 每次询问大模型前 | 更新提示词、精简对话历史 |
| wrap_model_call | 围绕每次模型调用 | 拦截并修改请求/响应 |
| wrap_tool_call | 围绕每次工具调用 | 拦截并修改工具执行 |
| after_model | 每次大模型回答后 | 检查回答安全性、合规性 |
| after_agent | 整个Agent运行完成后 | 保存结果、清理资源 |
当使用多个Middleware时,它们的执行顺序非常重要。Middleware会按照添加的顺序形成一个"层层包裹"的结构:
code复制用户请求
├─ 中间件1.before_agent
│ ├─ 中间件2.before_agent
│ │ ├─ Agent核心处理
│ │ └─ 中间件2.after_agent
└─ 中间件1.after_agent
返回结果
这种设计意味着:
因此,合理的Middleware排列顺序应该是:
LangChain提供了一系列开箱即用的中间件,下面我们详细解析几个最常用的内置中间件。
PII(Personally Identifiable Information)Middleware能够自动检测和隐藏敏感个人信息,如邮箱、电话号码等。这对于处理用户输入的AI应用至关重要。
python复制from langchain.agents.middleware import PIIMiddleware
# 创建带PII保护的Agent
agent = create_agent(
middleware=[
PIIMiddleware("email", strategy="mask", apply_to_input=True),
PIIMiddleware(
"phone_number",
detector=r"(?:\+?\d{1,3}[\s.-]?)?(?:\(?\d{2,4}\)?[\s.-]?)?\d{3,4}[\s.-]?\d{4}",
strategy="block"
)
]
)
| 输入内容 | 处理策略 | 输出结果 |
|---|---|---|
| "我的邮箱是test@example.com" | mask | "我的邮箱是tes****@example.com" |
| "我的手机是13800138000" | block | 抛出异常:检测到手机号 |
| "身份证号是110101199003077654" | replace | "身份证号是[REDACTED]" |
当对话轮次过多或内容过长时,SummarizationMiddleware可以自动生成对话摘要,避免上下文过长导致的性能问题。
python复制from langchain.agents.middleware import SummarizationMiddleware
middleware = SummarizationMiddleware(
model=llm,
trigger=[
("messages", 4), # 对话超过4轮后触发
("tokens", 1000) # 或总Token数超过1000后触发
],
keep=("messages", 2), # 保留最新的2条原始消息
)
对于某些敏感操作,HumanInTheLoopMiddleware可以在执行前暂停流程,等待人工审核。
python复制from langchain.agents.middleware import HumanInTheLoopMiddleware
middleware = HumanInTheLoopMiddleware(
interrupt_on={
"send_email": { # 只有send_email工具需要审核
"allowed_decisions": ["approve", "edit", "reject"]
}
}
)
当内置中间件无法满足需求时,我们可以开发自定义中间件。下面通过一个购车推荐场景的案例,演示如何创建业务特定的中间件。
假设我们需要一个根据用户预算动态调整推荐内容的中间件:
python复制from dataclasses import dataclass
from typing import Callable
from langchain.agents.middleware import AgentMiddleware
from langchain.agents.middleware.types import ModelRequest, ModelResponse
@dataclass
class CarContext:
budget_range: str = "10-20万"
class CarBudgetMiddleware(AgentMiddleware):
def warp_model_call(
self,
model_request: ModelRequest,
handler: Callable[[ModelRequest], ModelResponse]
) -> ModelResponse:
# 从上下文中获取预算范围
budget_range = model_request.runtime.context.budget_range
# 根据预算调整可用工具
if budget_range == "20-30万":
model_request.tools = [mid_range_car_recommendation, compare_models]
else:
model_request.tools = [economy_car_recommendation, compare_models]
# 添加预算提示
budget_hint = f"\n[系统提示: 您的购车预算为{budget_range}]"
model_request.messages[-1].content += budget_hint
return handler(model_request)
python复制# 创建带自定义中间件的Agent
car_agent = create_agent(
model=llm,
tools=[economy_car_recommendation, mid_range_car_recommendation, compare_models],
middleware=[CarBudgetMiddleware()],
context_schema=CarContext
)
# 使用不同预算进行测试
response1 = car_agent.invoke({
"messages": [HumanMessage(content="推荐家庭用车")],
"runtime": {"context": CarContext(budget_range="10-20万")}
})
response2 = car_agent.invoke({
"messages": [HumanMessage(content="推荐商务用车")],
"runtime": {"context": CarContext(budget_range="20-30万")}
})
现在,我们将结合多个Middleware,构建一个既强大又安全的AI代理系统。
假设我们要开发一个客户服务AI代理,需要满足:
python复制from langchain.agents import create_agent
from langchain.agents.middleware import (
PIIMiddleware,
SummarizationMiddleware,
HumanInTheLoopMiddleware
)
# 组合多个中间件
agent = create_agent(
model=llm,
tools=[query_order, send_email, upgrade_service],
middleware=[
# 第一层:隐私保护
PIIMiddleware("email", strategy="mask"),
PIIMiddleware("phone", strategy="block"),
# 第二层:对话管理
SummarizationMiddleware(
model=llm,
trigger=[("messages", 5), ("tokens", 1200)],
keep=("messages", 3)
),
# 第三层:业务逻辑
HumanInTheLoopMiddleware(
interrupt_on={
"send_email": {"allowed_decisions": ["approve", "reject"]},
"upgrade_service": {"allowed_decisions": ["approve", "edit"]}
}
),
# 第四层:权限控制
UserLevelMiddleware()
]
)
在实际使用Middleware过程中,可能会遇到以下典型问题:
问题现象:多个中间件相互干扰,产生预期外的行为
解决方案:
问题现象:添加中间件后系统响应明显变慢
优化建议:
问题现象:中间件之间需要共享复杂状态,导致代码混乱
设计建议:
问题现象:中间件链式调用导致问题难以追踪
调试技巧:
除了基本功能外,Middleware还可以实现一些高级应用模式:
通过中间件实现不同策略的A/B测试:
python复制class ABTestMiddleware(AgentMiddleware):
def __init__(self, variants):
self.variants = variants
def before_model(self, request, handler):
# 随机选择测试变体
variant = random.choice(self.variants)
# 修改请求参数实现不同策略
request.model_params.update(variant.params)
return handler(request)
使用中间件控制功能开关:
python复制class FeatureToggleMiddleware(AgentMiddleware):
def __init__(self, features):
self.features = features
def wrap_tool_call(self, tool_call, handler):
# 检查工具是否已启用
if tool_call.tool_name not in self.features.enabled_tools:
raise Exception("功能暂未开放")
return handler(tool_call)
通过中间件实现租户特定的处理逻辑:
python复制class TenantAwareMiddleware(AgentMiddleware):
def before_agent(self, request, handler):
tenant_id = parse_tenant_id(request)
# 加载租户特定配置
request.context.tenant_config = load_tenant_config(tenant_id)
return handler(request)
自动检查AI行为是否符合法规要求:
python复制class ComplianceMiddleware(AgentMiddleware):
def after_model(self, response, handler):
if not check_compliance(response.content):
response.content = "抱歉,我无法提供该信息"
return handler(response)
Middleware的设计灵活性使其能够适应各种复杂的业务需求和安全要求,是构建企业级AI应用不可或缺的组件。通过合理设计和组合中间件,开发者可以构建出既强大又安全的AI代理系统。