LangChain 1.0 中间件详解

一 概述与设计目标

  • 定位 :在 LangChain 1.0 中,中间件是围绕智能体执行流程的"可插拔钩子系统",用于在关键节点对输入、调用、输出进行预处理、拦截、修改与验证,从而实现更强的可控性与可观测性。

  • 核心能力

    • 上下文工程:动态提示词、对话摘要、上下文编辑,避免上下文溢出与跑偏。

    • 流程控制:重试、回退、速率限制、提前终止、条件跳转。

    • 安全与合规PII检测与脱敏、工具调用权限、人机协同(HITL)。

    • 可观测与成本:日志、监控、缓存、调用预算。

  • 执行模型

    • 顺序before_*钩子按注册顺序执行;after_*钩子按逆序执行。

    • 嵌套wrap_*钩子呈"洋葱式"嵌套,外层先进入、内层先返回。

    • 跳转 :在 before_model/after_model可返回 {"jump_to": "end|tools|model"}实现流程中断与跳转。

  • 与 create_agent 的关系create_agent 是 1.0 构建智能体的标准接口,底层基于 LangGraph 1.0 运行时 ,天然具备持久化、流式、HITL、时间回溯等能力,中间件即插即用。

二 执行顺序与跳转机制

  • 执行顺序规则

    • before_agentbefore_modelwrap_model_call(外→内)→ 模型调用 → wrap_model_call(内→外)→ after_model(逆序)→ wrap_tool_call(外→内)→ 工具执行 → wrap_tool_call(内→外)→ after_agent
  • 跳转控制

    • before_model/after_model返回 {"jump_to": "end|tools|model"}可中断并跳转;若从 before_model/after_model跳转到 "model",会重新触发该节点之前的 before_model钩子。

    • 使用跳转需在钩子上应用 @hook_config(can_jump_to=[...])明确声明合法目标。

  • 典型用途

    • 合规拦截:检测到敏感操作时 jump_to="end"终止并返回提示。

    • 条件路由:根据用户等级/意图跳过部分工具或直接进入特定处理分支。

三 内置中间件速览

名称 类别 作用时机 关键参数与作用
SummarizationMiddleware 任务适配 before_model model(摘要模型)、max_tokens_before_summary(触发阈值)、messages_to_keep(保留条数)、summary_prompttoken_counter(自定义计Token)
HumanInTheLoopMiddleware 流程控制 wrap_tool_call / after_model interrupt_on={"tool_name": {"allowed_decisions": ["approve","edit","reject"]}},可配 descriptiondescription_prefix
PIIMiddleware 强制规范 before_model / after_model pii_type(如 email/phone_number/credit_card)、strategy(block/redact/mask/hash)、detector(自定义正则/函数)、apply_to_input/output/tool_results
ModelFallbackMiddleware 流程控制 wrap_model_call first_model+ additional_models,主模型失败时自动降级
ToolCallLimitMiddleware 强制规范 before_model tool_name(可选,限定目标工具)、thread_limit(会话级上限)、run_limit(单次执行上限)、exit_behavior(end/error)
ModelCallLimitMiddleware 强制规范 before_model 与上类似,面向"模型调用次数"而非"工具调用次数"
ToolRetryMiddleware 流程控制 wrap_tool_call 重试策略与异常匹配,工具执行失败时自动重试
ToolEmulatorMiddleware(或 LLMToolEmulator) 任务适配 wrap_tool_call 模拟工具执行,用于离线演练/单元测试
AnthropicPromptCachingMiddleware 成本/性能 wrap_model_call 启用 Anthropic 提示缓存,减少重复计算
TokenBudgetMiddleware 成本/性能 before_model Token 预算与配额控制,超预算则阻断或降级

以上中间件覆盖了上下文优化、人工介入、隐私合规、调用限制、容错降级、成本控制等主流生产诉求。

四 自定义中间件实战

  • 装饰器方式(单钩点、轻量)

    • 适合快速添加"日志、动态提示词、单点重试/校验"等能力。

    • 示例:动态提示词 + 条件跳转 + 安全校验

      复制代码
      from langchain.agents.middleware import before_model, after_model, wrap_model_call, AgentMiddleware, AgentState, ModelRequest, ModelResponse, dynamic_prompt, hook_config
      from langchain_core.messages import AIMessage
      from typing import Any, Callable, Optional
      
      # before_model:记录消息数
      @before_model
      def log_msg_count(state: AgentState, runtime: Any) -> None:
          print(f"[BeforeModel] 消息数: {len(state['messages'])}")
      
      # after_model:合规拦截
      @after_model(can_jump_to=["end"])
      def block_sensitive(state: AgentState, runtime: Any) -> Optional[dict[str, Any]]:
          last = state["messages"][-1].content
          if "DELETE_ALL" in last.upper():
              return {"messages": [AIMessage("拒绝高危操作。")], "jump_to": "end"}
          return None
      
      # wrap_model_call:失败重试
      @wrap_model_call
      def retry_on_error(req: ModelRequest, handler: Callable[[ModelRequest], ModelResponse]) -> ModelResponse:
          for i in range(3):
              try:
                  return handler(req)
              except Exception as e:
                  if i == 2:
                      raise
                  print(f"重试 {i+1}/3: {e}")
  • 类方式(多钩点、可配置)

    • 适合"能力分级、多租户策略、复合规则"等复杂场景。

    • 示例:按用户等级动态切换模型与工具

      复制代码
      from dataclasses import dataclass
      from langchain.agents.middleware import AgentMiddleware
      
      @dataclass
      class UserContext:
          level: str  # "beginner" | "expert"
      
      class ExpertiseMiddleware(AgentMiddleware):
          def __init__(self, default_model, default_tools, expert_model, expert_tools):
              self.default_model = default_model
              self.default_tools = default_tools
              self.expert_model = expert_model
              self.expert_tools = expert_tools
      
          def before_model(self, state: AgentState, runtime: Any) -> None:
              ctx: UserContext = runtime.context.get("user") or UserContext(level="beginner")
              if ctx.level == "expert":
                  state["model"] = self.expert_model
                  state["tools"] = self.expert_tools
              else:
                  state["model"] = self.default_model
                  state["tools"] = self.default_tools
    • 使用方式:将上述中间件按需加入 create_agent(middleware=[...])即可生效。

五 最佳实践与选型建议

  • 保持单一职责:每个中间件只做一件事;组合多个中间件实现复杂能力。

  • 优先内置,再做扩展 :优先使用 SummarizationMiddleware、PIIMiddleware、HumanInTheLoopMiddleware、ModelFallbackMiddleware、ToolCallLimitMiddleware等,减少自研成本。

  • 顺序很重要:将"全局限制/安全护栏"类中间件靠前;"审计/日志"类靠后,避免被提前短路。

  • 优雅处理错误:在重试/回退/拦截中避免抛出未捕获异常导致流程中断。

  • 可观测优先:配合日志、指标与缓存中间件,确保可追踪、可回放、可优化。

  • 与 LangGraph 协同 :中间件提供"轻量定制",当需要复杂编排、持久化、细粒度状态机 时,可在 create_agent基础上深入 LangGraph 1.0运行时。

相关推荐
软件供应链安全指南2 小时前
“基于‘多模态SCA+全周期协同’的中间件开源风险治理实践”荣获OSCAR开源+安全及风险治理案例
安全·中间件·开源
无心水2 小时前
【中间件:Redis】4、Redis缓存实战:穿透/击穿/雪崩的5种解决方案(附代码实现)
redis·缓存·中间件·缓存穿透·缓存雪崩·分布式缓存·redis缓存问题
FreeCode19 小时前
LangChain1.0智能体开发:MCP
后端·langchain·agent
DO_Community1 天前
在 DigitalOcean GPU 云服务上使用 LangChain 构建Serverless AI 应用
人工智能·langchain·serverless
FreeCode1 天前
LangChain1.0智能体开发:上下文工程
后端·langchain·agent
凤凰战士芭比Q2 天前
web中间件——Nginx
前端·nginx·中间件
“负拾捌”2 天前
LangChain 中 ChatPromptTemplate 的几种使用方式
python·langchain·prompt
mobº2 天前
K8s 集群部署中间件 - yaml 版本(二)
中间件·容器·kubernetes