LangChain自定义中间件

一、核心概念(文档原文通俗翻译)

  1. 自定义中间件是什么? 自己写的、可插入 Agent 执行流程的钩子函数 / 增强逻辑 ,不用改 Agent 主代码,就能在调用模型前 / 后调用工具前 / 后插入自定义逻辑。
  2. 作用日志打印、参数修改、结果过滤、权限校验、数据格式化、自定义监控等。
  3. 运行位置 插在 Agent 的推理 → 调用模型 → 执行工具 全流程中,非侵入式增强
  4. 必须继承 所有自定义中间件都要继承官方基类:from langchain.agents.middleware import AgentMiddleware

二、官方规定的固定结构(必须遵守)

文档明确要求:自定义中间件必须实现 __call__ 方法方法签名固定:

复制代码
async def __call__(self, run, agent, input, **kwargs):
  • run:Agent 原始执行函数(必须调用它才能继续流程)
  • agent:当前 Agent 对象
  • input:用户输入
  • **kwargs:其他上下文参数

执行流程(文档核心)

  1. 执行前置逻辑(调用 run 之前)
  2. 调用 await run(agent, input, **kwargs) → 让 Agent 正常运行
  3. 执行后置逻辑(拿到结果后)
  4. 返回最终结果

三、官方示例 + 优化版代码(可直接运行)

1. 最简单的日志中间件(文档基础示例)

作用:在 Agent 运行前后打印日志

复制代码
from langchain.agents.middleware import AgentMiddleware
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI

# 自定义中间件:必须继承 AgentMiddleware
class LoggingMiddleware(AgentMiddleware):
    # 固定方法名和参数
    async def __call__(self, run, agent, input, **kwargs):
        # 【前置】运行前逻辑
        print(f"\n[日志中间件] 用户输入:{input}")
        
        # 执行 Agent 原始流程(必须写!)
        result = await run(agent, input,** kwargs)
        
        # 【后置】运行后逻辑
        print(f"[日志中间件] Agent 输出:{result}")
        
        # 返回结果
        return result

# 创建带自定义中间件的 Agent
agent = create_agent(
    llm=ChatOpenAI(model="gpt-3.5-turbo"),
    tools=[],  # 无工具演示
    middleware=[LoggingMiddleware()],  # 直接插入
)

2. 输入过滤中间件(文档扩展场景)

作用:拦截敏感词、修改用户输入

复制代码
class InputFilterMiddleware(AgentMiddleware):
    def __init__(self, forbidden_words: list):
        self.forbidden_words = forbidden_words

    async def __call__(self, run, agent, input,** kwargs):
        # 前置:检查敏感词
        lower_input = input.lower()
        for word in self.forbidden_words:
            if word in lower_input:
                return "❌ 输入包含敏感内容,已拦截"

        # 无敏感词则正常执行
        result = await run(agent, input, **kwargs)
        return result

# 使用:拦截包含"密码""银行卡"的请求
agent = create_agent(
    llm=ChatOpenAI(model="gpt-3.5-turbo"),
    tools=[],
    middleware=[InputFilterMiddleware(forbidden_words=["密码", "银行卡"])],
)

3. 结果修改中间件(文档高级用法)

作用:修改 Agent 最终返回结果

复制代码
class ResultFormatMiddleware(AgentMiddleware):
    async def __call__(self, run, agent, input,** kwargs):
        # 先执行原流程
        result = await run(agent, input, **kwargs)
        
        # 后置:格式化结果
        formatted = f""" 
        处理结果:{result}✅ 已通过自定义中间件格式化
        """
        return formatted

四、官方支持的两种使用方式

方式 1:创建时直接传入(推荐)

复制代码
agent = create_agent(
    llm=model,
    tools=tools,
    middleware=[MyMiddleware()],  # 列表形式,可多个按顺序执行
)

方式 2:动态添加

复制代码
agent = create_agent(llm=model, tools=tools)
agent.middleware.append(MyMiddleware())  # 动态追加

五、多个中间件执行规则(文档重点)

  • 顺序执行:列表里写在前面的先运行
  • 洋葱模型
    1. 中间件 1 前置 → 中间件 2 前置
    2. Agent 核心执行
    3. 中间件 2 后置 → 中间件 1 后置

六、完整可运行模板(官方标准写法)

复制代码
from langchain.agents.middleware import AgentMiddleware
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI

# 自定义中间件(官方标准结构)
class CustomMiddleware(AgentMiddleware):
    async def __call__(self, run, agent, input,** kwargs):
        # ======================
        # 【前置逻辑】写在这里
        # ======================
        print("→ 运行前:自定义处理输入")

        # 执行 Agent 主逻辑(必须调用)
        result = await run(agent, input, **kwargs)

        # ======================
        # 【后置逻辑】写在这里
        # ======================
        print("→ 运行后:自定义处理结果")

        # 返回最终结果
        return result

# 初始化
model = ChatOpenAI(model="gpt-3.5-turbo")
agent = create_agent(llm=model, tools=[], middleware=[CustomMiddleware()])

# 测试运行
# await agent.ainvoke("你好")

七、文档重点规则总结

  1. 必须继承 AgentMiddleware
  2. 必须实现 async def __call__(self, run, agent, input, **kwargs)
  3. 必须调用 await run(...) 才能让 Agent 继续执行
  4. 支持同步 / 异步(官方推荐异步)
  5. 多个中间件按列表顺序执行
  6. 非侵入式,不修改原有 Agent 代码

总结

  • 自定义中间件 = Agent 的前置 / 后置钩子
  • 固定结构:继承 + 实现 __call__ + 调用 run()
  • 用途:日志、过滤、修改、监控、权限控制等
  • 完全遵循官方规范,可直接集成到生产环境
相关推荐
汀沿河2 小时前
3 LangChain 1.0 中间件(Middleware)- after_model、after_agent
前端·中间件·langchain
java1234_小锋3 小时前
基于LangChain的RAG与Agent智能体开发 - 使用LangChain调用大语言模型
人工智能·语言模型·langchain·rag
chaors3 小时前
从零学RAG0x0c:AdvancedRAG检索优化-混合检索
langchain·llm·ai编程
chaors3 小时前
从零学RAG0x08:AdvancedRAG摘要索引 & 父子索引优化
人工智能·langchain·ai编程
chaors4 小时前
从零学RAG0x0a:AdvancedRAG查询优化-问题丰富 & 问题拆解
人工智能·langchain·ai编程
chaors4 小时前
从零学RAG0x09:AdvancedRAG假设性文档 & 元数据索引优化
人工智能·langchain·ai编程
xht08324 小时前
docker离线安装及部署各类中间件(x86系统架构)
docker·中间件·系统架构
勇气要爆发5 小时前
吴恩达《LangChain LLM 应用开发精读笔记》8-Document Loading 文档加载
笔记·langchain·dreamweaver
怕浪猫5 小时前
第4章 提示工程基础:Prompt Templates
langchain·llm·ai编程