LangGraph 生产级部署全解:FastAPI + Docker

一、部署架构总览

我们将基于你之前的带人工干预的双智能体系统,构建一个完整的生产级部署方案,包含三个核心部分:

  1. FastAPI 接口层:封装 Agent 为标准 HTTP 接口,支持任务启动、人工干预、状态查询
  2. Redis 持久化层:替代 MemorySaver,实现状态持久化和服务重启恢复
  3. Docker 容器化:打包整个应用为镜像,实现一键部署和环境一致性

标准部署架构图

plaintext

复制代码
客户端 → FastAPI 接口 → LangGraph Agent → Redis(状态持久化)

二、第一步:项目结构标准化

先将你的代码整理为生产级项目结构:

plaintext

复制代码
langgraph-agent-deploy/
├── agent/                  # Agent核心逻辑
│   ├── __init__.py
│   ├── multi_agent.py      # 双智能体系统代码
│   └── state.py            # 状态定义
├── main.py                 # FastAPI入口
├── requirements.txt        # 依赖清单
├── Dockerfile              # 镜像构建文件
├── docker-compose.yml      # 服务编排
└── .env                    # 环境变量配置

三、第二步:FastAPI 接口封装

3.1 核心依赖安装

bash

运行

复制代码
pip install fastapi uvicorn python-multipart langgraph-checkpoint-redis

3.2 完整 FastAPI 代码

复制代码
# main.py
import asyncio
from typing import Optional
from fastapi import FastAPI, HTTPException, CORS
from pydantic import BaseModel
from langgraph.types import Command
from agent.multi_agent import build_multi_agent_system
from agent.state import MultiAgentState

# 初始化FastAPI
app = FastAPI(title="LangGraph 双智能体写作系统 API", version="1.0.0")

# 配置CORS,允许前端跨域访问
app.add_middleware(
    CORS,
    allow_origins=["*"],  # 生产环境改为具体域名
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 初始化Agent系统(全局单例,避免重复初始化)
agent = build_multi_agent_system()

# ==================== 请求响应模型 ====================
class StartTaskRequest(BaseModel):
    thread_id: str
    task: str
    topic: str

class ResumeTaskRequest(BaseModel):
    thread_id: str
    human_input: str

class TaskStatusResponse(BaseModel):
    thread_id: str
    status: str  # running, interrupted, completed, failed
    current_step: Optional[str] = None
    interrupt_info: Optional[dict] = None
    final_article: Optional[str] = None
    error: Optional[str] = None

# ==================== 核心接口 ====================
@app.post("/api/task/start", response_model=TaskStatusResponse)
async def start_task(request: StartTaskRequest):
    """启动一个新的写作任务"""
    try:
        config = {"configurable": {"thread_id": request.thread_id}}
        
        # 初始化任务状态
        initial_state: MultiAgentState = {
            "task": request.task,
            "topic": request.topic,
            "research_notes": "",
            "draft": "",
            "final_article": "",
            "current_agent": "researcher",
            "turn_count": 0,
            "max_turns": 5,
            "messages": [],
            "error": None,
            "human_feedback": ""
        }

        # 异步执行Agent,避免阻塞事件循环
        result = await asyncio.to_thread(
            agent.invoke,
            initial_state,
            config=config
        )

        # 构建响应
        return await _build_status_response(request.thread_id, result)

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"任务启动失败: {str(e)}")

@app.post("/api/task/resume", response_model=TaskStatusResponse)
async def resume_task(request: ResumeTaskRequest):
    """恢复被中断的任务,传入人类反馈"""
    try:
        config = {"configurable": {"thread_id": request.thread_id}}
        
        # 用Command恢复执行
        result = await asyncio.to_thread(
            agent.invoke,
            Command(resume=request.human_input),
            config=config
        )

        return await _build_status_response(request.thread_id, result)

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"任务恢复失败: {str(e)}")

@app.get("/api/task/status/{thread_id}", response_model=TaskStatusResponse)
async def get_task_status(thread_id: str):
    """查询任务当前状态"""
    try:
        config = {"configurable": {"thread_id": thread_id}}
        
        # 获取最新状态
        state = await asyncio.to_thread(agent.get_state, config)
        result = state.values

        return await _build_status_response(thread_id, result)

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"状态查询失败: {str(e)}")

# ==================== 辅助函数 ====================
async def _build_status_response(thread_id: str, result: dict) -> TaskStatusResponse:
    """构建统一的状态响应"""
    # 检查是否有中断
    if "__interrupt__" in result:
        interrupt_info = result["__interrupt__"][0]["value"]
        return TaskStatusResponse(
            thread_id=thread_id,
            status="interrupted",
            current_step=interrupt_info["type"],
            interrupt_info=interrupt_info,
            error=result.get("error")
        )
    
    # 检查是否完成
    if result.get("final_article"):
        return TaskStatusResponse(
            thread_id=thread_id,
            status="completed",
            final_article=result["final_article"],
            error=result.get("error")
        )
    
    # 检查是否出错
    if result.get("error"):
        return TaskStatusResponse(
            thread_id=thread_id,
            status="failed",
            error=result["error"]
        )
    
    # 运行中
    return TaskStatusResponse(
        thread_id=thread_id,
        status="running",
        current_step=result.get("current_agent"),
        error=result.get("error")
    )

# 启动服务
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

3.3 修改 Agent 代码,使用 Redis 持久化

将之前的MemorySaver替换为RedisSaver,实现状态持久化:

复制代码
# agent/multi_agent.py
import os
from langgraph.checkpoint.redis import RedisSaver

def build_multi_agent_system():
    # ... 其他代码不变 ...

    # 从环境变量获取Redis连接地址
    redis_url = os.getenv("REDIS_URI", "redis://localhost:6379/0")
    checkpointer = RedisSaver.from_url(redis_url)

    return builder.compile(checkpointer=checkpointer)

四、第三步:Docker 容器化

4.1 编写 requirements.txt

复制代码
# requirements.txt
fastapi==0.115.0
uvicorn==0.30.6
python-multipart==0.0.12
langgraph==0.2.39
langchain==0.2.16
langchain-openai==0.1.25
pydantic-settings==2.5.2
python-dotenv==1.0.1
langgraph-checkpoint-redis==1.0.11
redis==5.2.1

4.2 编写 Dockerfile(多阶段构建,优化镜像体积)

dockerfile

复制代码
# Dockerfile
# 第一阶段:构建阶段
FROM python:3.11-slim AS builder

# 设置工作目录
WORKDIR /app

# 安装系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    && rm -rf /var/lib/apt/lists/*

# 创建虚拟环境
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade pip \
    && pip install --no-cache-dir -r requirements.txt

# 第二阶段:运行阶段
FROM python:3.11-slim

# 设置工作目录
WORKDIR /app

# 复制虚拟环境
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# 创建非root用户,增强安全性
RUN useradd -m appuser
USER appuser

# 复制应用代码
COPY --chown=appuser:appuser . .

# 暴露端口
EXPOSE 8000

# 启动命令
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

4.3 编写 docker-compose.yml

yaml

复制代码
# docker-compose.yml
version: '3.8'

volumes:
  redis-data:
    driver: local

services:
  # Redis服务:状态持久化
  redis:
    image: redis:7-alpine
    container_name: langgraph-redis
    restart: unless-stopped
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 1s
      retries: 5

  # LangGraph Agent API服务
  langgraph-agent:
    build: .
    container_name: langgraph-agent
    restart: unless-stopped
    ports:
      - "8000:8000"
    depends_on:
      redis:
        condition: service_healthy
    env_file:
      - .env
    environment:
      - REDIS_URI=redis://redis:6379/0
      - PYTHONUNBUFFERED=1  # 禁用Python输出缓冲,确保日志实时显示

4.4 编写 .env 配置文件

env

复制代码
# .env
# 智谱API配置
ZHIPU_API_KEY=你的智谱API密钥
ZHIPU_BASE_URL=https://open.bigmodel.cn/api/paas/v4
LLM_MODEL=glm-4.6
LLM_BACKUP_MODEL=glm-4-flash
LLM_TIMEOUT=30

# Redis配置(docker-compose中会覆盖这个值)
REDIS_URI=redis://localhost:6379/0

五、第四步:部署与运行

5.1 一键启动所有服务

复制代码
# 构建镜像并启动服务
docker-compose up -d --build

# 查看服务状态
docker-compose ps

# 查看日志
docker-compose logs -f langgraph-agent

5.2 测试 API 接口

1. 启动任务
复制代码
curl -X POST http://localhost:8000/api/task/start \
  -H "Content-Type: application/json" \
  -d '{
    "thread_id": "test_task_001",
    "task": "写一篇关于LangGraph多智能体系统的技术文章",
    "topic": "LangGraph多智能体系统的原理、架构与实现"
  }'
2. 查询任务状态

bash

复制代码
curl http://localhost:8000/api/task/status/test_task_001
3. 恢复中断任务(当任务等待人工确认时)

bash

复制代码
curl -X POST http://localhost:8000/api/task/resume \
  -H "Content-Type: application/json" \
  -d '{
    "thread_id": "test_task_001",
    "human_input": "通过"
  }'
4. 访问自动生成的 API 文档

六、生产环境优化最佳实践

6.1 性能优化

  1. 增加 Worker 进程数 :在 Dockerfile 的 CMD 中调整--workers参数,通常设置为 CPU 核心数的 2-4 倍

  2. 使用 Gunicorn + Uvicorn :生产环境推荐用 Gunicorn 管理 Uvicorn Worker,提高并发能力

    dockerfile

    复制代码
    CMD ["gunicorn", "main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "-b", "0.0.0.0:8000"]
  3. 添加 Nginx 反向代理:处理静态资源、SSL 终止、负载均衡

6.2 安全优化

  1. 限制 CORS 来源 :将allow_origins=["*"]改为具体的前端域名
  2. 添加 API 密钥认证:给接口添加 API 密钥验证,防止未授权访问
  3. 使用 Docker Secrets:生产环境不要用.env 文件存储敏感信息,改用 Docker Secrets 或 Kubernetes Secrets
  4. 定期更新基础镜像:及时修复安全漏洞

6.3 可观测性

  1. 添加日志配置:配置结构化日志,方便日志收集和分析

  2. 添加健康检查接口

    python

    复制代码
    @app.get("/health")
    async def health_check():
        return {"status": "healthy", "timestamp": datetime.now().isoformat()}
  3. 集成监控系统:用 Prometheus + Grafana 监控服务指标

6.4 高可用部署

  1. 多实例部署:启动多个 Agent 实例,用 Nginx 或 Kubernetes 进行负载均衡
  2. Redis 集群:生产环境使用 Redis 集群,保证数据高可用
  3. 自动扩缩容:根据请求量自动调整实例数量

七、常见问题排查

  1. Redis 连接失败:检查 docker-compose 中的 Redis 服务是否正常启动,REDIS_URI 是否正确
  2. 接口超时:增加 Uvicorn 的超时时间,或优化 Agent 执行逻辑
  3. 状态丢失:确保使用了 RedisSaver,并且 Redis 数据卷配置正确
  4. 镜像体积过大:使用多阶段构建,删除不必要的依赖和文件

按照这个方案部署后,你的 LangGraph Agent 系统就具备了生产级的稳定性、可扩展性和可维护性,可以安全地对外提供服务。

相关推荐
CLX05052 小时前
C#怎么实现全局异常过滤器_C#如何捕获控制器报错【核心】
jvm·数据库·python
码农阿豪2 小时前
Docker 部署 XiuXianGame 文字修仙游戏:极空间 NAS 上随时挂机刷资源
游戏·docker·容器
码以致用2 小时前
FastAPI 从入门到实践:构建规范的 RESTful API 服务
后端·restful·fastapi
性野喜悲2 小时前
python将excel中的链接转成图片并替换链接展示在excel中【将pdf的第一页插入excel并将对应信息获取到插入签名等位置】
开发语言·python·excel
Marvel__Dead2 小时前
基于 AI 大模型的百度旋转验证识别(通用能力极强)
人工智能·爬虫·python·验证码识别·ai 大模型
code bean2 小时前
【LangChain 】 自定义解析器实战指南:从原理到 10 个业务场景落地
算法·langchain
Leinwin2 小时前
OpenAI Daybreak实战指南:如何将AI安全检查嵌入你的开发流程
后端·python·flask
monkeyhlj2 小时前
LangChain - V1.0
python·langchain·ai编程
zh路西法2 小时前
【Qwen2.5本地部署】超简单pytorch-gpu部署教程
人工智能·pytorch·python