LangServe 介绍和使用

发布于:2025-03-25 ⋅ 阅读:(33) ⋅ 点赞:(0)

LangServe 创建

LangServe 核心组成

LangServe 是 LangChain 的官方服务化框架,包含以下核心模块:

组件 作用 技术实现
FastAPI Server 提供REST API服务端点 FastAPI框架
LCEL Integration 自动将LCEL链转换为API端点 路由生成器
Playground 交互式API测试界面 Swagger UI定制
Client SDK 自动生成Python/JS客户端代码 Pydantic模型生成
Async Support 支持异步请求处理 Starlette底层
Schema Validation 输入输出Schema验证 Pydantic模型

项目创建流程(使用langchain-cli)

步骤1:环境准备
# 安装langchain-cli(需Python≥3.8)
pip install -U langchain-cli

# 验证安装
langchain --help  # 应显示命令列表
步骤2:初始化项目
# 创建新项目目录
langchain new my-langserve-app  # 交互式选择"API Server"模板

# 目录结构说明
'''
my-langserve-app/
├── app/                  # 主应用目录
│   ├── chains/           # LCEL链定义
│   ├── server.py         # FastAPI入口文件
│   └── config.py         # 配置文件
├── tests/                # 测试用例
├── requirements.txt      # 依赖列表
├── .env                  # 环境变量
└── pyproject.toml        # 项目元数据
'''
步骤3:添加自定义链
# 在项目目录内执行
langchain add my-chain  # 自动生成chains/my_chain.py模板
步骤4:编写链逻辑
# app/chains/my_chain.py
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_template("用比喻解释: {concept}")
model = ChatOpenAI(model="gpt-3.5-turbo")

chain = (
    {"concept": RunnablePassthrough()} 
    | prompt 
    | model 
    | (lambda x: x.content)
)
步骤5:配置服务端路由
# app/server.py
from fastapi import FastAPI
from app.chains.my_chain import chain
from langserve import add_routes

app = FastAPI(
    title="LangChain Server",
    version="1.0",
    description="API文档示例"
)

# 注册链端点
add_routes(
    app,
    chain.with_types(input_type=str),  # 显式声明输入类型
    path="/explain",  # API端点路径
    enable_feedback_endpoint=True  # 启用反馈端点
)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

核心配置文件解析

环境变量配置(.env)
OPENAI_API_KEY=sk-your-key  # 必须配置
LANGCHAIN_TRACING_V2=true   # 启用LangSmith监控
LANGCHAIN_PROJECT=MyServe   # 监控项目名称
依赖管理(requirements.txt)
fastapi>=0.95.0
langchain-openai
langserve>=0.0.19
uvicorn
python-dotenv

启动与测试服务

启动服务
cd my-langserve-app
python -m app.server  # 或使用uvicorn直接启动
访问端点
  • API文档:http://localhost:8000/docs
  • Playground:http://localhost:8000/explain/playground
  • OpenAPI规范:http://localhost:8000/openapi.json
使用curl测试
curl -X POST http://localhost:8000/explain/invoke \
  -H "Content-Type: application/json" \
  -d '{"input": "量子物理"}'

高级功能实现

输入输出Schema定制
from pydantic import BaseModel

class InputSchema(BaseModel):
    concept: str
    difficulty: str = "beginner"

class OutputSchema(BaseModel):
    explanation: str
    metaphors_used: int

def parse_output(text: str) -> dict:
    return {
        "explanation": text,
        "metaphors_used": text.count("如")
    }

custom_chain = chain | parse_output

# 注册时指定输入输出模型
add_routes(
    app,
    custom_chain.with_types(
        input_type=InputSchema,
        output_type=OutputSchema
    ),
    path="/custom-explain"
)
添加中间件
# CORS中间件示例
from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)
日志配置
import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[logging.StreamHandler()]
)

通过以上步骤,您可以快速搭建具备生产级能力的LangServe服务。关键要点是:

  1. 标准化链开发:通过LCEL保证链的可服务化
  2. 配置即代码:利用langchain-cli生成最佳实践结构
  3. 全链路可观测:集成监控和日志
  4. 客户端友好:自动生成的SDK降低集成成本

Langserve 目录结构详解

标准项目目录结构

my-langserve-app/
├── app/                   # 主应用代码
│   ├── __init__.py
│   ├── chains/           # LCEL链定义目录
│   │   ├── __init__.py
│   │   └── example.py    # 示例链定义
│   ├── server.py         # FastAPI入口文件
│   ├── config.py         # 配置管理
│   └── middleware.py     # 自定义中间件(可选)
├── tests/                # 测试用例
│   └── test_server.py    # API测试
├── requirements.txt      # 依赖管理
├── .env                  # 环境变量
├── .gitignore            # Git排除配置
├── Dockerfile            # 容器化配置
├── pyproject.toml        # 项目元数据
└── README.md             # 项目文档

核心文件详解

app/chains/ 目录

作用:存放所有 LCEL 链的定义文件

# app/chains/example.py 示例
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate

def create_chain():
    prompt = ChatPromptTemplate.from_template("解释 {concept} 就像我是5岁小孩")
    model = ChatOpenAI(model="gpt-3.5-turbo")
    
    return (
        {"concept": RunnablePassthrough()}
        | prompt
        | model
        | (lambda x: x.content)
    )
app/server.py

作用:FastAPI 主入口文件

from fastapi import FastAPI
from app.chains.example import create_chain
from langserve import add_routes
from app.config import settings

app = FastAPI(
    title="LangChain Server",
    version=settings.VERSION,
    description=settings.DESCRIPTION
)

# 注册链路由
chain = create_chain()
add_routes(
    app,
    chain.with_types(input_type=str),
    path="/explain",
    enable_feedback_endpoint=True  # 启用反馈端点
)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        app, 
        host=settings.HOST, 
        port=settings.PORT
    )
app/config.py

作用:集中管理配置参数

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    HOST: str = "0.0.0.0"
    PORT: int = 8000
    VERSION: str = "1.0.0"
    DESCRIPTION: str = "LangChain服务示例"
    OPENAI_API_KEY: str
    
    class Config:
        env_file = ".env"

settings = Settings()
app/middleware.py (可选)

作用:自定义中间件

from fastapi import Request

async def log_middleware(request: Request, call_next):
    print(f"Request: {request.method} {request.url}")
    response = await call_next(request)
    return response

支持文件解析

requirements.txt

作用:声明项目依赖

fastapi>=0.95.0
langchain-openai
langserve>=0.0.19
uvicorn[standard]
python-dotenv>=0.19.0
pydantic-settings>=2.0.0
.env

作用:存储敏感配置

# 最小配置示例
OPENAI_API_KEY=sk-your-key-here
LANGCHAIN_TRACING_V2=true
LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
LANGCHAIN_API_KEY=ls-your-key
LANGCHAIN_PROJECT=LangServe-Prod
tests/test_server.py

作用:API测试用例

from fastapi.testclient import TestClient
from app.server import app

client = TestClient(app)

def test_explain_endpoint():
    response = client.post(
        "/explain/invoke",
        json={"input": "量子力学"}
    )
    assert response.status_code == 200
    assert "量子" in response.json()["output"]
Dockerfile

作用:容器化部署配置

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["gunicorn", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "app.server:app"]

扩展目录结构(高级项目)

对于复杂项目,推荐扩展为:

app/
├── api/
│   ├── v1/              # API版本目录
│   │   ├── endpoints/
│   │   │   └── explain.py
│   │   └── __init__.py
│   └── v2/              # 新版API
├── core/                # 核心业务逻辑
│   └── llm_processing.py
├── models/              # Pydantic模型
│   └── schemas.py
├── utils/               # 工具函数
│   └── logger.py
├── config/              # 配置管理
│   ├── __init__.py
│   └── settings.py
└── dependencies.py      # FastAPI依赖项

关键文件最佳实践

配置管理进阶
# app/config/settings.py
from pydantic_settings import BaseSettings
from pydantic import Field

class AppSettings(BaseSettings):
    PROJECT_NAME: str = Field(..., env="PROJECT_NAME")
    LOG_LEVEL: str = Field("INFO", env="LOG_LEVEL")

class LLMSettings(BaseSettings):
    OPENAI_API_KEY: str = Field(..., env="OPENAI_API_KEY")
    OPENAI_MODEL: str = Field("gpt-4", env="OPENAI_MODEL")

class Settings(AppSettings, LLMSettings):
    pass

settings = Settings()
路由分离管理
# app/api/v1/endpoints/explain.py
from fastapi import APIRouter
from langserve import add_routes
from app.chains.example import create_chain

router = APIRouter(prefix="/v1")

chain = create_chain()
add_routes(
    router,
    chain.with_types(input_type=str),
    path="/explain"
)

# app/server.py 主文件
from app.api.v1.endpoints import explain
app.include_router(explain.router)
自定义中间件集成
# app/middleware.py
import time
from fastapi import Request

class TimingMiddleware:
    def __init__(self, app):
        self.app = app

    async def __call__(self, scope, receive, send):
        start_time = time.time()
        await self.app(scope, receive, send)
        process_time = time.time() - start_time
        print(f"请求处理时间: {process_time:.2f}s")

# app/server.py
from app.middleware import TimingMiddleware
app.add_middleware(TimingMiddleware)

关键目录作用总结

目录/文件 核心作用 典型内容示例
app/chains/ 存放可复用的LCEL链定义 问答链/摘要链/分类链
app/config/ 集中管理配置参数 模型参数/API密钥/服务端口
app/api/ 按版本组织的API端点 v1/question-answering
app/core/ 核心业务逻辑实现 数据处理/算法实现
app/models/ 定义Pydantic数据模型 请求/响应模型
app/utils/ 公共工具函数 日志记录/数据库连接
app/server.py FastAPI主入口点 中间件/路由聚合/生命周期管理

通过这种结构化的组织方式,可以实现:

  1. 模块化开发:各功能模块解耦
  2. 配置集中管理:避免散落各处的魔法值
  3. 版本控制:支持多API版本并存
  4. 易于扩展:新增功能不影响现有结构
  5. 团队协作友好:清晰的职责划分

接口编写和调用

服务端开发

编写业务链
# app/chains/demo_chain.py
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough

def create_chain():
    prompt = ChatPromptTemplate.from_template(
        """将以下概念转换为表情符号:
概念:{concept}
表情符号:"""
    )
    model = ChatOpenAI(temperature=0.7)
    
    return (
        {"concept": RunnablePassthrough()}
        | prompt
        | model
        | (lambda x: x.content)
    )
配置服务入口
# app/server.py
from fastapi import FastAPI
from langserve import add_routes
from app.chains.demo_chain import create_chain
from app.config import settings

app = FastAPI(
    title="表情符号转换服务",
    version="1.0",
    description="将抽象概念转换为表情符号组合"
)

# 注册主链
chain = create_chain()
add_routes(
    app,
    chain.with_types(input_type=str),
    path="/emojify",
    enable_feedback_endpoint=True
)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host=settings.HOST, port=settings.PORT)

客户端调用方式

Python 客户端调用
# client.py
import requests
from langserve.client import RemoteRunnable

# 方式1:使用 requests 直接调用
def call_via_http(concept: str):
    response = requests.post(
        "http://localhost:8000/emojify/invoke",
        json={"input": concept}
    )
    return response.json()["output"]

# 方式2:使用 LangServe 客户端
chain = RemoteRunnable("http://localhost:8000/emojify")

# 同步调用
print(chain.invoke("爱情"))          # 输出:💘🌹💌

# 异步调用
async def async_call():
    print(await chain.ainvoke("科技"))  # 输出:🖥️🚀🔬

# 批量调用
print(chain.batch(["夏天", "音乐"]))  # 输出:["☀️🏖️🍹", "🎵🎧🎤"]

# 流式调用
for chunk in chain.stream("旅行"):
    print(chunk, end="", flush=True)  # 逐步输出:✈️🌍🧳
CURL 调用
curl -X POST http://localhost:8000/emojify/invoke \
  -H "Content-Type: application/json" \
  -d '{"input": "圣诞节"}'
# 响应示例:{"output": "🎄🎅🦌"}
使用 Playground

访问 http://localhost:8000/emojify/playground 进行交互测试

运行与验证

启动服务端
python -m app.server
测试输出验证

服务启动后会出现以下端点:

INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO:     API docs: http://localhost:8000/docs
INFO:     Playground: http://localhost:8000/emojify/playground
客户端执行
python client.py

高级配置扩展

添加输入验证
# 在 app/chains/demo_chain.py 中添加
from pydantic import BaseModel, Field

class EmojiRequest(BaseModel):
    concept: str = Field(..., min_length=2, max_length=50)
    style: str = Field("default", enum=["default", "funny", "professional"])

def create_chain():
    # ...原有代码...
    return (
        {"concept": RunnablePassthrough()}  # 改为接收 EmojiRequest
        | prompt
        | model
        | (lambda x: x.content)
    ).with_types(input_type=EmojiRequest)  # 声明输入模型
添加速率限制
# app/server.py 中添加
from fastapi.middleware import Middleware
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
from slowapi import Limiter
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter

@app.get("/")
@limiter.limit("5/minute")
async def root(request: Request):
    return {"status": "OK"}

生产部署方案

生产部署核心要素

要素 要求 工具/技术
容器化 环境一致性 Docker + 多阶段构建
编排 自动扩缩容 Kubernetes + HPA
服务暴露 高可用 + 负载均衡 Nginx/HAProxy + Ingress
监控 全链路可观测 Prometheus + Grafana
安全 加密 + 访问控制 Let’s Encrypt + RBAC
CI/CD 自动化发布 GitHub Actions + ArgoCD

Docker 生产级配置

优化Dockerfile
# 阶段1:构建环境
FROM python:3.9-slim as builder

WORKDIR /app
COPY requirements.txt .

RUN apt-get update && apt-get install -y gcc python3-dev \
    && pip install --user -r requirements.txt

# 阶段2:运行环境
FROM python:3.9-slim

WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .

ENV PATH=/root/.local/bin:$PATH
ENV PYTHONPATH=/app

# 非root用户运行
RUN groupadd -r langserve && useradd -r -g langserve langserve \
    && chown -R langserve:langserve /app
USER langserve

CMD ["gunicorn", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "app.server:app"]
构建与运行
# 构建镜像
docker build -t langserve-prod:v1 .

# 运行容器
docker run -d \
  -p 8000:8000 \
  -v ./env:/app/.env \
  --name langserve-app \
  langserve-prod:v1

Kubernetes 部署方案

Deployment配置
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: langserve-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: langserve
  template:
    metadata:
      labels:
        app: langserve
    spec:
      containers:
      - name: langserve
        image: langserve-prod:v1
        ports:
        - containerPort: 8000
        envFrom:
        - secretRef:
            name: langserve-secrets
        resources:
          limits:
            memory: "512Mi"
            cpu: "1000m"
          requests:
            memory: "256Mi"
            cpu: "500m"
Service与Ingress
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: langserve-service
spec:
  selector:
    app: langserve
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8000

---
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: langserve-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
  - hosts:
    - api.yourdomain.com
    secretName: langserve-tls
  rules:
  - host: api.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: langserve-service
            port:
              number: 80

云平台部署示例(AWS ECS)

task-definition.json
{
  "family": "langserve-task",
  "networkMode": "awsvpc",
  "executionRoleArn": "arn:aws:iam::1234567890:role/ecsTaskRole",
  "containerDefinitions": [
    {
      "name": "langserve",
      "image": "langserve-prod:v1",
      "portMappings": [
        {
          "containerPort": 8000,
          "protocol": "tcp"
        }
      ],
      "secrets": [
        {
          "name": "OPENAI_API_KEY",
          "valueFrom": "arn:aws:ssm:us-east-1:1234567890:parameter/langserve/openai-key"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/langserve",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ],
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "1024",
  "memory": "2048"
}
部署命令
aws ecs register-task-definition --cli-input-json file://task-definition.json
aws ecs create-service --cluster prod-cluster --service-name langserve-service \
  --task-definition langserve-task --desired-count 3 --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[subnet-12345],securityGroups=[sg-67890]}"

生产优化配置

Gunicorn高级配置
# gunicorn_config.py
workers = 4
worker_class = "uvicorn.workers.UvicornWorker"
bind = "0.0.0.0:8000"
timeout = 120
keepalive = 5
accesslog = "-"
errorlog = "-"
环境变量管理
# 使用Kubernetes Secrets
kubectl create secret generic langserve-secrets \
  --from-literal=OPENAI_API_KEY='sk-xxx' \
  --from-literal=LANGSMITH_API_KEY='ls_xxx'
健康检查配置
# app/server.py
@app.get("/healthz")
async def health_check():
    return {"status": "ok", "checks": {
        "database": "connected",
        "llm": "responsive"
    }}

监控与日志

Prometheus指标收集
# app/monitoring.py
from prometheus_fastapi_instrumentator import Instrumentator

def setup_monitoring(app):
    Instrumentator().instrument(app).expose(app)
Grafana仪表板
{
  "panels": [
    {
      "type": "graph",
      "title": "请求率",
      "targets": [{
        "expr": "rate(langserve_http_requests_total[5m])",
        "legendFormat": "{{route}}"
      }]
    }
  ]
}
日志聚合(ELK Stack)
# 使用Loguru配置
from loguru import logger
import sys

logger.add(
    sys.stderr,
    format="{time} {level} {message}",
    level="INFO"
)
logger.add(
    "/var/log/langserve.json",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}",
    rotation="100 MB",
    serialize=True  # 输出JSON格式
)

安全加固措施

速率限制
# app/security.py
from fastapi import FastAPI
from fastapi.middleware import Middleware
from slowapi import Limiter
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)
app = FastAPI(middleware=[Middleware(limiter)])

@app.get("/")
@limiter.limit("10/minute")
async def root():
    return {"message": "OK"}
JWT认证
# app/auth.py
from fastapi.security import OAuth2PasswordBearer
from fastapi import Depends, HTTPException

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

async def verify_token(token: str = Depends(oauth2_scheme)):
    if not validate_jwt(token):
        raise HTTPException(status_code=403)
    return token

# 在路由中使用
@app.get("/secure")
async def secure_route(token: str = Depends(verify_token)):
    return {"data": "secure"}

Langserve DEBUG

基础调试方法

启用详细日志
# 在server.py开头添加
import logging
logging.basicConfig(
    level=logging.DEBUG,  # 设置为DEBUG级别
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("debug.log"),
        logging.StreamHandler()
    ]
)
环境变量控制
# .env 文件
LANGCHAIN_VERBOSE=true  # 启用LangChain详细日志
LOG_LEVEL=DEBUG

LangSmith 追踪

配置LangSmith
# app/config.py
from langsmith import Client

class Settings(BaseSettings):
    LANGCHAIN_TRACING_V2: bool = True
    LANGCHAIN_ENDPOINT: str = "https://api.smith.langchain.com"
    LANGCHAIN_API_KEY: str
    LANGCHAIN_PROJECT: str = "DebugProject"
    
# 在server.py中初始化
client = Client()
查看追踪记录

访问 https://smith.langchain.com 查看:

  • 请求耗时分解
  • 各步骤输入输出
  • Token使用统计
  • 异常堆栈追踪

断点调试

在LCEL链中插入断点
from langchain_core.runnables import RunnableLambda

def debug_step(input_data):
    import pdb; pdb.set_trace()  # 传统断点
    # 或使用IDE断点
    print(f"中间状态: {input_data}")
    return input_data

chain = (
    prompt 
    | model 
    | RunnableLambda(debug_step)  # 插入调试步骤
    | output_parser
)
VS Code调试配置
// .vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "LangServe Debug",
            "type": "python",
            "request": "launch",
            "program": "app/server.py",
            "env": {
                "OPENAI_API_KEY": "${env:OPENAI_API_KEY}",
                "LANGCHAIN_TRACING_V2": "true"
            },
            "args": [],
            "jinja": true
        }
    ]
}

请求/响应日志

自定义中间件
# app/middleware.py
import time
from fastapi import Request

async def log_middleware(request: Request, call_next):
    start_time = time.time()
    
    # 记录请求
    logger.debug(f"Request: {request.method} {request.url}")
    if request.method == "POST":
        body = await request.body()
        logger.debug(f"Request Body: {body.decode()}")
    
    response = await call_next(request)
    
    # 记录响应
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    logger.debug(f"Response Status: {response.status_code}")
    logger.debug(f"Response Body: {response.body.decode()}")
    
    return response

# 在server.py中添加
app.add_middleware(log_middleware)
示例日志输出
2024-02-20 10:00:00 - middleware - DEBUG - Request: POST /emojify/invoke
2024-02-20 10:00:00 - middleware - DEBUG - Request Body: {"input": "爱情"}
2024-02-20 10:00:02 - middleware - DEBUG - Response Status: 200
2024-02-20 10:00:02 - middleware - DEBUG - Response Body: {"output": "💘🌹💌"}

异常处理

全局异常处理器
from fastapi import FastAPI, HTTPException
from fastapi.exceptions import RequestValidationError

@app.exception_handler(Exception)
async def global_exception_handler(request, exc):
    logger.error(f"全局异常: {str(exc)}", exc_info=True)
    return JSONResponse(
        status_code=500,
        content={"detail": "内部服务器错误"}
    )

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    logger.warning(f"参数错误: {exc.errors()}")
    return JSONResponse(
        status_code=422,
        content={"detail": exc.errors()}
    )
自定义异常
class LLMOverloadError(Exception):
    def __init__(self, message="模型过载"):
        self.message = message
        super().__init__(self.message)

@app.get("/health")
async def health_check():
    if not check_llm_available():  # 假设的检查函数
        raise LLMOverloadError()
    return {"status": "ok"}

@app.exception_handler(LLMOverloadError)
async def llm_exception_handler(request, exc):
    return JSONResponse(
        status_code=503,
        content={"detail": exc.message}
    )

高级调试技巧

中间变量捕获
from langchain_core.runnables import RunnableParallel

debuggable_chain = RunnableParallel(
    original_output=chain,
    intermediate=some_step  # 捕获特定步骤的输出
)

# 调用时获取额外信息
result = debuggable_chain.invoke("量子物理")
print(result["intermediate"])
回调系统
from langchain_core.callbacks import BaseCallbackHandler

class DebugCallback(BaseCallbackHandler):
    def on_chain_start(self, serialized, inputs, **kwargs):
        print(f"链启动: {serialized['id'][-1]} 输入: {inputs}")

    def on_chain_end(self, outputs, **kwargs):
        print(f"链结束 输出: {outputs}")

# 调用时注入
chain.invoke("太空探索", config={"callbacks": [DebugCallback()]})

性能分析

使用cProfile
python -m cProfile -o profile_stats.prof -m app.server
snakeviz profile_stats.prof  # 生成可视化报告
内存分析
# 在需要分析的代码块使用
from memory_profiler import profile

@profile(precision=4)
def critical_function():
    # 需要分析的代码
    result = chain.invoke("大数据")
    return result

调试工具对比

工具/方法 适用场景 优势 限制
LangSmith 全链路追踪 可视化/生产环境可用 需要网络连接
pdb 本地单步调试 无需额外配置 不适用异步代码
IDE调试器 复杂逻辑分析 变量监控/条件断点 需要IDE支持
日志系统 生产环境问题排查 长期记录/性能分析 需要存储空间
cProfile 性能瓶颈定位 精确到函数级耗时统计 影响运行时性能

通过组合使用这些调试技术,您可以:

  1. 快速定位逻辑错误
  2. 分析性能瓶颈
  3. 监控生产环境异常
  4. 验证数据流正确性
  5. 优化资源利用率

关键原则:在开发阶段使用交互式调试,测试环境启用详细日志,生产环境使用追踪系统+适当日志级别。