LangChain v1.0+ 与 FastAPI 中间件深度解析:从概念到实战

【个人主页:玄同765

大语言模型(LLM)开发工程师中国传媒大学·数字媒体技术(智能交互与游戏设计)

**深耕领域:**大语言模型开发 / RAG知识库 / AI Agent落地 / 模型微调

**技术栈:**Python / LangChain/RAG(Dify+Redis+Milvus)| SQL/NumPy | FastAPI+Docker ️

**工程能力:**专注模型工程化部署、知识库构建与优化,擅长全流程解决方案

「让AI交互更智能,让技术落地更高效」

欢迎技术探讨/项目合作! 关注我,解锁大模型与智能交互的无限可能!


一、什么是中间件?

1.1 中间件的核心思想

中间件(Middleware) 是一种软件设计模式,它允许你在请求处理流程的特定节点插入自定义逻辑,而无需修改核心业务的代码。

核心思想可以概括为:关注点分离(Separation of Concerns)

  • 将横切关注点(日志、认证、限流等)从核心业务逻辑中剥离
  • 通过可组合的拦截器增强系统灵活性
  • 实现代码复用和模块化设计

1.2 中间件的典型应用场景

场景 说明 示例
日志记录 记录请求/响应信息 记录 API 调用日志
认证授权 验证用户身份和权限 JWT Token 验证
限流控制 防止系统过载 限制 API 调用频率
错误处理 统一异常处理 全局异常捕获
数据转换 请求/响应数据加工 JSON 序列化、加密解密
性能监控 统计执行时间 接口性能分析

二、FastAPI 中间件详解

2.1 FastAPI 中间件架构

FastAPI 基于 Starlette 框架,采用经典的**洋葱模型(Onion Model)**中间件架构:

复制代码
请求进入
    ↓
┌─────────────────────────────────────┐
│  Middleware 1 (before)              │
│  ┌───────────────────────────────┐  │
│  │  Middleware 2 (before)        │  │
│  │  ┌─────────────────────────┐  │  │
│  │  │  Middleware 3 (before)  │  │  │
│  │  │  ┌─────────────────┐    │  │  │
│  │  │  │   Route Handler │    │  │  │
│  │  │  │   (核心业务)     │    │  │  │
│  │  │  └─────────────────┘    │  │  │
│  │  │  Middleware 3 (after)   │  │  │
│  │  └─────────────────────────┘  │  │
│  │  Middleware 2 (after)         │  │
│  └───────────────────────────────┘  │
│  Middleware 1 (after)               │
└─────────────────────────────────────┘
    ↓
响应返回

2.2 创建 FastAPI 中间件

FastAPI 提供两种创建中间件的方式:

方式一:使用装饰器(推荐)
复制代码
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import time

app = FastAPI()

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    """
    计算请求处理时间的中间件
    """
    start_time = time.time()
  
    # 调用下一个中间件或路由处理器
    response = await call_next(request)
  
    # 在响应头中添加处理时间
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
  
    return response
方式二:继承 BaseHTTPMiddleware
复制代码
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class LoggingMiddleware(BaseHTTPMiddleware):
    """
    日志记录中间件
    """
    async def dispatch(self, request: Request, call_next):
        # 记录请求信息
        logger.info(f"Request: {request.method} {request.url}")
      
        # 调用下一个处理器
        response = await call_next(request)
      
        # 记录响应信息
        logger.info(f"Response: {response.status_code}")
      
        return response

app = FastAPI()
app.add_middleware(LoggingMiddleware)

2.3 FastAPI 中间件实战案例

案例 1:JWT 认证中间件
复制代码
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
import jwt
from datetime import datetime

class JWTAuthMiddleware(BaseHTTPMiddleware):
    """
    JWT 认证中间件
    验证请求头中的 Authorization Token
    """
    def __init__(self, app, secret_key: str, exclude_paths: list = None):
        super().__init__(app)
        self.secret_key = secret_key
        self.exclude_paths = exclude_paths or ["/login", "/register"]
  
    async def dispatch(self, request: Request, call_next):
        # 跳过不需要认证的路径
        if request.url.path in self.exclude_paths:
            return await call_next(request)
      
        # 获取 Authorization Header
        auth_header = request.headers.get("Authorization")
        if not auth_header:
            return JSONResponse(
                status_code=401,
                content={"detail": "Missing authorization header"}
            )
      
        try:
            # 提取 Token
            scheme, token = auth_header.split()
            if scheme.lower() != "bearer":
                raise ValueError("Invalid scheme")
          
            # 验证 Token
            payload = jwt.decode(token, self.secret_key, algorithms=["HS256"])
          
            # 将用户信息添加到请求状态
            request.state.user = payload
          
        except jwt.ExpiredSignatureError:
            return JSONResponse(
                status_code=401,
                content={"detail": "Token has expired"}
            )
        except Exception as e:
            return JSONResponse(
                status_code=401,
                content={"detail": f"Invalid token: {str(e)}"}
            )
      
        # 继续处理请求
        response = await call_next(request)
        return response

# 使用中间件
app = FastAPI()
app.add_middleware(
    JWTAuthMiddleware,
    secret_key="your-secret-key",
    exclude_paths=["/docs", "/openapi.json", "/login"]
)
案例 2:速率限制中间件
复制代码
import time
from collections import defaultdict
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware
from fastapi.responses import JSONResponse

class RateLimitMiddleware(BaseHTTPMiddleware):
    """
    基于内存的速率限制中间件
    限制每个 IP 每分钟最多 60 次请求
    """
    def __init__(self, app, max_requests: int = 60, window: int = 60):
        super().__init__(app)
        self.max_requests = max_requests
        self.window = window
        # 存储每个 IP 的请求记录: {ip: [(timestamp1), (timestamp2), ...]}
        self.requests = defaultdict(list)
  
    async def dispatch(self, request: Request, call_next):
        client_ip = request.client.host
        current_time = time.time()
      
        # 清理过期的请求记录
        self.requests[client_ip] = [
            req_time for req_time in self.requests[client_ip]
            if current_time - req_time < self.window
        ]
      
        # 检查是否超过限制
        if len(self.requests[client_ip]) >= self.max_requests:
            return JSONResponse(
                status_code=429,
                content={
                    "detail": "Rate limit exceeded",
                    "retry_after": self.window
                }
            )
      
        # 记录本次请求
        self.requests[client_ip].append(current_time)
      
        # 添加限流相关响应头
        response = await call_next(request)
        response.headers["X-RateLimit-Limit"] = str(self.max_requests)
        response.headers["X-RateLimit-Remaining"] = str(
            self.max_requests - len(self.requests[client_ip])
        )
      
        return response
案例 3:CORS 中间件(内置)
复制代码
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# 配置 CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000", "https://yourdomain.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["*"],
    max_age=3600,
)

三、LangChain v1.0+ Agent 中间件详解

3.1 LangChain 中间件的设计背景

LangChain v1.0(2025 年 10 月 22 日发布)对 Agent 系统进行了彻底重构,中间件(Middleware) 是这次重构的核心特性之一。

为什么需要中间件?

在 v0.x 版本中,控制 Agent 行为主要依赖 Callbacks 机制:

复制代码
# v0.x 时代的 Callbacks(已弃用)
from langchain.callbacks.base import BaseCallbackHandler

class MyCallback(BaseCallbackHandler):
    def on_llm_start(self, serialized, prompts, **kwargs):
        pass
  
    def on_tool_start(self, serialized, input_str, **kwargs):
        pass

Callbacks 的问题:

  • ❌ 无法修改请求/响应数据
  • ❌ 无法中断执行流程
  • ❌ 控制能力有限

v1.0 中间件的优势

  • ✅ 完整的请求/响应控制
  • ✅ 支持中断和重试
  • ✅ 可组合、可复用
  • ✅ 类型安全

3.2 LangChain 中间件架构

LangChain Agent 中间件采用**钩子函数(Hooks)**设计模式:

复制代码
用户输入
    ↓
before_agent (Agent 执行前)
    ↓
before_model (调用模型前)
    ↓
wrap_model_call (包装模型调用)
    ↓
模型实际调用
    ↓
after_model (模型调用后)
    ↓
wrap_tool_call (包装工具调用)
    ↓
工具实际执行
    ↓
after_agent (Agent 执行后)
    ↓
返回结果

3.3 创建 LangChain 中间件

基础中间件结构
复制代码
from langchain.agents.middleware import AgentMiddleware
from typing import Any, Dict, List, Optional

class MyMiddleware(AgentMiddleware):
    """
    自定义 Agent 中间件
    """
  
    async def before_agent(
        self,
        query: str,
        context: Dict[str, Any]
    ) -> Dict[str, Any]:
        """
        Agent 执行前调用
        可以修改用户查询、添加上下文等
        """
        print(f"[Before Agent] Query: {query}")
        return {"query": query, "context": context}
  
    async def before_model(
        self,
        messages: List[Dict[str, Any]],
        context: Dict[str, Any]
    ) -> List[Dict[str, Any]]:
        """
        调用模型前调用
        可以修改消息列表、添加系统提示等
        """
        print(f"[Before Model] Messages count: {len(messages)}")
        return messages
  
    async def after_model(
        self,
        response: Any,
        context: Dict[str, Any]
    ) -> Any:
        """
        模型调用后调用
        可以处理模型输出、记录日志等
        """
        print(f"[After Model] Response: {response}")
        return response
  
    async def wrap_tool_call(
        self,
        tool_name: str,
        tool_input: Dict[str, Any],
        context: Dict[str, Any]
    ) -> Any:
        """
        包装工具调用
        可以添加重试逻辑、超时控制等
        """
        print(f"[Tool Call] {tool_name}: {tool_input}")
        # 调用实际工具
        result = await self.call_tool(tool_name, tool_input)
        return result
注册中间件到 Agent
复制代码
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI

# 创建 LLM
llm = ChatOpenAI(model="gpt-4")

# 创建工具列表
tools = [...]

# 创建中间件列表
middleware = [
    MyMiddleware(),
    # 可以添加更多中间件...
]

# 创建带中间件的 Agent
agent = create_agent(
    llm=llm,
    tools=tools,
    middleware=middleware
)

# 使用 Agent
result = await agent.ainvoke({"input": "查询北京天气"})

3.4 LangChain 内置中间件

LangChain v1.0 提供了丰富的内置中间件:

1. HumanInTheLoopMiddleware(人工审核)
复制代码
from langchain.agents.middleware import HumanInTheLoopMiddleware

# 创建人工审核中间件
human_middleware = HumanInTheLoopMiddleware(
    # 在以下情况下暂停等待人工确认
    pause_on_tool_calls=True,  # 工具调用前暂停
    pause_on_completion=False,  # 完成后不暂停
    custom_prompt="请确认是否执行此操作:"
)

agent = create_agent(
    llm=llm,
    tools=tools,
    middleware=[human_middleware]
)
2. ToolCallLimitMiddleware(工具调用限制)
复制代码
from langchain.agents.middleware import ToolCallLimitMiddleware

# 限制最多调用 5 个工具
limit_middleware = ToolCallLimitMiddleware(max_calls=5)

agent = create_agent(
    llm=llm,
    tools=tools,
    middleware=[limit_middleware]
)
3. ConversationSummaryMiddleware(对话摘要)
复制代码
from langchain.agents.middleware import ConversationSummaryMiddleware

# 当对话超过 10 轮时自动摘要
summary_middleware = ConversationSummaryMiddleware(
    max_turns=10,
    summary_model=llm  # 用于生成摘要的模型
)

agent = create_agent(
    llm=llm,
    tools=tools,
    middleware=[summary_middleware]
)
4. PIISanitizerMiddleware(PII 脱敏)
复制代码
from langchain.agents.middleware import PIISanitizerMiddleware
import re

class CustomPIISanitizer(PIISanitizerMiddleware):
    """
    自定义 PII 脱敏中间件
    """
    def sanitize(self, text: str) -> str:
        # 脱敏手机号
        text = re.sub(r'1[3-9]\d{9}', '***PHONE***', text)
        # 脱敏身份证号
        text = re.sub(r'\d{17}[\dXx]', '***ID***', text)
        # 脱敏邮箱
        text = re.sub(r'[\w.-]+@[\w.-]+\.\w+', '***EMAIL***', text)
        return text

pii_middleware = CustomPIISanitizer()

3.5 LangChain 中间件实战案例

案例 1:日志记录中间件
复制代码
import logging
from typing import Any, Dict, List
from langchain.agents.middleware import AgentMiddleware

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

class LoggingMiddleware(AgentMiddleware):
    """
    全面的日志记录中间件
    记录 Agent 执行的完整生命周期
    """
  
    async def before_agent(
        self,
        query: str,
        context: Dict[str, Any]
    ) -> Dict[str, Any]:
        logger.info(f"🚀 Agent 开始执行 | Query: {query}")
        context['start_time'] = time.time()
        return {"query": query, "context": context}
  
    async def before_model(
        self,
        messages: List[Dict[str, Any]],
        context: Dict[str, Any]
    ) -> List[Dict[str, Any]]:
        logger.info(f"🤖 调用模型 | Messages: {len(messages)}")
        return messages
  
    async def after_model(
        self,
        response: Any,
        context: Dict[str, Any]
    ) -> Any:
        logger.info(f"✅ 模型响应 | Content: {response.content[:100]}...")
        return response
  
    async def wrap_tool_call(
        self,
        tool_name: str,
        tool_input: Dict[str, Any],
        context: Dict[str, Any]
    ) -> Any:
        logger.info(f"🔧 调用工具 | {tool_name} | Input: {tool_input}")
      
        try:
            result = await self.call_tool(tool_name, tool_input)
            logger.info(f"✅ 工具执行成功 | {tool_name}")
            return result
        except Exception as e:
            logger.error(f"❌ 工具执行失败 | {tool_name} | Error: {e}")
            raise
  
    async def after_agent(
        self,
        result: Any,
        context: Dict[str, Any]
    ) -> Any:
        duration = time.time() - context.get('start_time', 0)
        logger.info(f"🏁 Agent 执行完成 | 耗时: {duration:.2f}s")
        return result
案例 2:重试机制中间件
复制代码
import asyncio
from typing import Any, Dict
from langchain.agents.middleware import AgentMiddleware

class RetryMiddleware(AgentMiddleware):
    """
    工具调用重试中间件
    当工具调用失败时自动重试
    """
  
    def __init__(self, max_retries: int = 3, delay: float = 1.0):
        self.max_retries = max_retries
        self.delay = delay
  
    async def wrap_tool_call(
        self,
        tool_name: str,
        tool_input: Dict[str, Any],
        context: Dict[str, Any]
    ) -> Any:
        last_exception = None
      
        for attempt in range(self.max_retries):
            try:
                result = await self.call_tool(tool_name, tool_input)
                if attempt > 0:
                    logger.info(f"✅ 第 {attempt + 1} 次重试成功")
                return result
            except Exception as e:
                last_exception = e
                logger.warning(
                    f"⚠️ 工具调用失败 | {tool_name} | "
                    f"第 {attempt + 1} 次尝试 | Error: {e}"
                )
              
                if attempt < self.max_retries - 1:
                    wait_time = self.delay * (2 ** attempt)  # 指数退避
                    logger.info(f"⏳ 等待 {wait_time}s 后重试...")
                    await asyncio.sleep(wait_time)
      
        # 所有重试都失败
        logger.error(f"❌ 工具调用最终失败 | {tool_name}")
        raise last_exception
案例 3:权限控制中间件
复制代码
from typing import Any, Dict, List
from langchain.agents.middleware import AgentMiddleware

class PermissionMiddleware(AgentMiddleware):
    """
    工具权限控制中间件
    根据用户角色限制可使用的工具
    """
  
    def __init__(self, user_role: str):
        self.user_role = user_role
        # 定义角色权限映射
        self.role_permissions = {
            "admin": ["*"],  # 管理员可以使用所有工具
            "user": ["search", "calculator", "weather"],  # 普通用户
            "guest": ["calculator"]  # 访客
        }
  
    def _can_use_tool(self, tool_name: str) -> bool:
        """检查用户是否有权限使用工具"""
        allowed_tools = self.role_permissions.get(self.user_role, [])
        return "*" in allowed_tools or tool_name in allowed_tools
  
    async def wrap_tool_call(
        self,
        tool_name: str,
        tool_input: Dict[str, Any],
        context: Dict[str, Any]
    ) -> Any:
        if not self._can_use_tool(tool_name):
            raise PermissionError(
                f"用户角色 '{self.user_role}' 无权使用工具 '{tool_name}'"
            )
      
        return await self.call_tool(tool_name, tool_input)

四、FastAPI 与 LangChain 中间件对比

4.1 设计理念对比

维度 FastAPI 中间件 LangChain 中间件
设计模式 洋葱模型(Onion Model) 钩子函数(Hooks)
核心思想 请求/响应拦截 生命周期干预
数据流向 单向:Request → Response 多阶段:多轮对话循环
状态管理 无状态(每次请求独立) 有状态(维护对话上下文)
组合方式 链式嵌套 列表顺序执行

4.2 实现机制对比

复制代码
# FastAPI: 洋葱模型,嵌套调用
async def middleware1(request, call_next):
    # 前置处理
    response = await call_next(request)  # 进入下一层
    # 后置处理
    return response

# LangChain: 钩子函数,阶段干预
class MyMiddleware(AgentMiddleware):
    async def before_agent(self, query, context):
        # Agent 执行前
        pass
  
    async def before_model(self, messages, context):
        # 模型调用前
        pass
  
    async def after_model(self, response, context):
        # 模型调用后
        pass

4.3 应用场景对比

场景 FastAPI LangChain
日志记录 ✅ HTTP 请求/响应日志 ✅ Agent 执行流程日志
认证授权 ✅ API 访问控制 ✅ 工具使用权限控制
限流控制 ✅ 接口频率限制 ✅ 模型调用次数限制
错误处理 ✅ HTTP 异常统一处理 ✅ 工具调用失败重试
数据转换 ✅ 请求/响应格式化 ✅ 消息内容脱敏/摘要
人工介入 ❌ 不适用 ✅ 人工审核确认

五、实战:构建完整的 Agent API 服务

5.1 项目架构

复制代码
agent_api/
├── main.py              # FastAPI 应用入口
├── middleware/
│   ├── __init__.py
│   ├── auth.py          # JWT 认证中间件
│   ├── rate_limit.py    # 限流中间件
│   └── logging.py       # 日志中间件
├── agent/
│   ├── __init__.py
│   ├── agent.py         # LangChain Agent 配置
│   └── middleware.py    # Agent 中间件
├── tools/
│   └── __init__.py      # 工具定义
└── requirements.txt

5.2 完整代码实现

1. LangChain Agent 中间件 (agent/middleware.py)
复制代码
import time
import logging
from typing import Any, Dict, List
from langchain.agents.middleware import AgentMiddleware

logger = logging.getLogger(__name__)

class AgentLoggingMiddleware(AgentMiddleware):
    """Agent 日志中间件"""
  
    async def before_agent(self, query: str, context: Dict[str, Any]):
        context['start_time'] = time.time()
        logger.info(f"[Agent] 开始处理: {query[:50]}...")
        return {"query": query, "context": context}
  
    async def wrap_tool_call(self, tool_name: str, tool_input: Dict, context: Dict):
        logger.info(f"[Agent] 调用工具: {tool_name}")
        start = time.time()
        result = await self.call_tool(tool_name, tool_input)
        logger.info(f"[Agent] 工具 {tool_name} 执行完成, 耗时: {time.time()-start:.2f}s")
        return result
  
    async def after_agent(self, result: Any, context: Dict):
        duration = time.time() - context.get('start_time', 0)
        logger.info(f"[Agent] 执行完成, 总耗时: {duration:.2f}s")
        return result


class AgentRateLimitMiddleware(AgentMiddleware):
    """Agent 调用限制中间件"""
  
    def __init__(self, max_tool_calls: int = 10):
        self.max_tool_calls = max_tool_calls
        self.call_count = 0
  
    async def wrap_tool_call(self, tool_name: str, tool_input: Dict, context: Dict):
        self.call_count += 1
        if self.call_count > self.max_tool_calls:
            raise Exception(f"工具调用次数超过限制: {self.max_tool_calls}")
        return await self.call_tool(tool_name, tool_input)
2. FastAPI 中间件 (middleware/)
复制代码
# middleware/logging.py
import time
import logging
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware

logger = logging.getLogger(__name__)

class APILoggingMiddleware(BaseHTTPMiddleware):
    """API 请求日志中间件"""
  
    async def dispatch(self, request: Request, call_next):
        start = time.time()
      
        # 记录请求
        logger.info(f"[API] {request.method} {request.url.path}")
      
        # 处理请求
        response = await call_next(request)
      
        # 记录响应
        duration = time.time() - start
        logger.info(
            f"[API] {request.method} {request.url.path} "
            f"- {response.status_code} - {duration:.3f}s"
        )
      
        return response


# middleware/rate_limit.py
import time
from collections import defaultdict
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware
from fastapi.responses import JSONResponse

class APIRateLimitMiddleware(BaseHTTPMiddleware):
    """API 限流中间件"""
  
    def __init__(self, app, max_requests: int = 100, window: int = 60):
        super().__init__(app)
        self.max_requests = max_requests
        self.window = window
        self.requests = defaultdict(list)
  
    async def dispatch(self, request: Request, call_next):
        client_ip = request.client.host
        current_time = time.time()
      
        # 清理过期记录
        self.requests[client_ip] = [
            t for t in self.requests[client_ip]
            if current_time - t < self.window
        ]
      
        # 检查限流
        if len(self.requests[client_ip]) >= self.max_requests:
            return JSONResponse(
                status_code=429,
                content={"error": "Rate limit exceeded"}
            )
      
        self.requests[client_ip].append(current_time)
        return await call_next(request)
3. FastAPI 主应用 (main.py)
复制代码
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import logging

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

# 导入中间件
from middleware.logging import APILoggingMiddleware
from middleware.rate_limit import APIRateLimitMiddleware

# 导入 Agent
from agent.agent import create_agent_with_middleware

app = FastAPI(title="Agent API Service")

# 添加 FastAPI 中间件
app.add_middleware(APILoggingMiddleware)
app.add_middleware(APIRateLimitMiddleware, max_requests=100, window=60)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["POST"],
    allow_headers=["*"],
)

# 创建 Agent 实例
agent = create_agent_with_middleware()


class QueryRequest(BaseModel):
    query: str
    session_id: str = "default"


class QueryResponse(BaseModel):
    result: str
    tool_calls: list
    duration: float


@app.post("/agent/query", response_model=QueryResponse)
async def agent_query(request: QueryRequest):
    """
    调用 Agent 处理查询
    """
    import time
    start = time.time()
  
    try:
        # 调用 Agent
        result = await agent.ainvoke({
            "input": request.query
        })
      
        duration = time.time() - start
      
        return QueryResponse(
            result=result["output"],
            tool_calls=result.get("intermediate_steps", []),
            duration=duration
        )
  
    except Exception as e:
        logging.error(f"Agent 执行失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@app.get("/health")
async def health_check():
    """健康检查"""
    return {"status": "healthy"}


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
4. Agent 配置 (agent/agent.py)
复制代码
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from langchain.tools import Tool

from agent.middleware import AgentLoggingMiddleware, AgentRateLimitMiddleware


def create_agent_with_middleware():
    """
    创建带中间件的 Agent
    """
    # 创建 LLM
    llm = ChatOpenAI(
        model="gpt-4",
        temperature=0.7
    )
  
    # 定义工具
    tools = [
        Tool(
            name="search",
            func=lambda x: f"搜索结果: {x}",
            description="搜索信息的工具"
        ),
        Tool(
            name="calculator",
            func=lambda x: str(eval(x)),
            description="计算数学表达式的工具"
        ),
    ]
  
    # 创建中间件
    middleware = [
        AgentLoggingMiddleware(),      # 日志记录
        AgentRateLimitMiddleware(max_tool_calls=10),  # 限流控制
    ]
  
    # 创建 Agent
    agent = create_agent(
        llm=llm,
        tools=tools,
        middleware=middleware
    )
  
    return agent

5.3 运行和测试

复制代码
# 安装依赖
pip install fastapi uvicorn langchain langchain-openai

# 启动服务
python main.py

# 测试 API
curl -X POST "http://localhost:8000/agent/query" \
  -H "Content-Type: application/json" \
  -d '{"query": "计算 123 * 456"}'

六、最佳实践与注意事项

6.1 FastAPI 中间件最佳实践

  1. 保持轻量:中间件应该快速执行,避免阻塞请求

  2. 异常处理:始终捕获异常,避免影响后续处理

  3. 状态管理:避免在中间件中存储请求相关的状态

  4. 顺序重要:中间件按照添加顺序嵌套执行

    ✅ 好的实践:快速执行,正确传递

    @app.middleware("http")
    async def good_middleware(request: Request, call_next):
    # 快速前置处理
    response = await call_next(request)
    # 快速后置处理
    return response

    ❌ 避免:长时间阻塞

    @app.middleware("http")
    async def bad_middleware(request: Request, call_next):
    time.sleep(5) # 不要这样做!
    response = await call_next(request)
    return response

6.2 LangChain 中间件最佳实践

  1. 幂等性:中间件应该可以安全地多次执行

  2. 上下文传递:使用 context 字典传递跨阶段数据

  3. 错误处理:提供有意义的错误信息

  4. 性能考虑:避免在关键路径上执行耗时操作

    ✅ 好的实践:使用 context 传递数据

    async def before_agent(self, query: str, context: Dict):
    context['start_time'] = time.time() # 记录开始时间
    return {"query": query, "context": context}

    async def after_agent(self, result: Any, context: Dict):
    duration = time.time() - context['start_time'] # 使用 context 数据
    return result

6.3 常见陷阱

陷阱 说明 解决方案
中间件顺序 顺序错误导致逻辑异常 仔细规划中间件执行顺序
异常吞噬 中间件捕获异常但不处理 始终正确传递或处理异常
状态泄漏 请求间状态相互影响 使用上下文对象,避免全局状态
性能瓶颈 中间件执行过慢 异步处理,避免阻塞操作
循环依赖 中间件间相互依赖 保持中间件独立性

七、总结

核心要点回顾

  1. 中间件的本质:在核心逻辑前后插入横切关注点的机制
  2. FastAPI 中间件:基于洋葱模型,适合 HTTP 请求/响应处理
  3. LangChain 中间件:基于钩子函数,适合 Agent 生命周期干预
  4. 两者结合:可以构建完整的 AI API 服务体系

选择建议

场景 推荐方案
纯 Web API 服务 FastAPI 中间件
AI Agent 应用 LangChain 中间件
Agent + API 服务 两者结合使用

学习路径建议

  1. 入门:先掌握 FastAPI 中间件,理解洋葱模型
  2. 进阶:学习 LangChain 中间件,理解钩子机制
  3. 实战:结合两者构建完整的 AI 应用
  4. 深入:阅读源码,理解底层实现原理

📚 延伸阅读

本文基于 FastAPI 0.100+ 和 LangChain v1.0+ 编写,建议读者使用最新版本进行实践。

相关推荐
AC赳赳老秦1 小时前
DeepSeek一体机部署:中小企业本地化算力成本控制方案
服务器·数据库·人工智能·zookeeper·时序数据库·terraform·deepseek
十铭忘1 小时前
动作识别11——自建数据集训练PoseC3D第6篇之第二次训练
人工智能·深度学习·计算机视觉
陈天伟教授1 小时前
人工智能应用-机器听觉:6. 拼接合成法
人工智能·语音识别
I'mChloe2 小时前
机器学习核心分支:深入解析监督学习
人工智能·学习·机器学习
Guheyunyi2 小时前
电气安全管理系统:筑牢现代用电安全的智能防线
大数据·人工智能·科技·安全·架构·能源
AI数据皮皮侠2 小时前
中国耕地利用强度数据(2018-2023)
大数据·人工智能·python·深度学习·机器学习
skywalk81632 小时前
免费且完全开源的金融平台,金融数据集软件openbb
人工智能·金融·openbb
学而要时习2 小时前
深度神经网络到AI大语言模型:一场被“误认为突然发生”的技术演进
人工智能·语言模型·dnn
OctShop大型商城源码2 小时前
大型多用户商城源码+收银系统源码+IM在线客服源码一体化OctShop
人工智能·商城系统·开源收银系统·im在线客服系统源码