LangGraph 前后端模板

一个使用FastAPI和WebSockets与React前端通信的LangGraph后端模板,支持模型响应生成和流式传输,简化了开发流程。

  • by durgapradeepch
  • JavaScript
  • 本地部署
  • 更新于
在 GitHub 查看 durgapradeepch/mcp-chatbot

使用说明

LangGraph Python后端带React TypeScript前端

🤓 太长,读不下去了

LangGraph 后端使用 快速API 和 WebSocket 沟通 反应 前端,显示模型生成 响应和流式传输,作为模板变得简单。运行通过 pip install -r requirements.txt 然后 ./start-local.sh --backend。查看下面的更多信息!

🏛 背景

作为 LangGraph 随着技术的发展,将需要建立实现无缝交互的最佳方式 在...之间 LangGraph 以及任何前端框架。LLM聊天设置中UI的一个关键方面是确保 机器人是 积极地 正在处理您发送的回复。确认可以采取各种形式,例如 作为一种视觉辅助工具,如旋转器、吐司、状态/进度条,或在生成令牌时流式传输令牌。 这是一个模板,旨在融合前端和后端之间的核心概念,以提供出色的用户体验 对于不了解LLM及其局限性的人来说,这是一种经验。

我发现流媒体方法非常成功,表明LLM认可了我的信息 正在生成响应。我使用WebSockets来处理前端之间的连接和通信 后端,便于集成 _LangChain_s 异步流事件 和 _反应_s 使用效果挂钩。此设置允许应用程序在以下时间等待机器人的响应 在生成令牌时同时流式传输令牌。我的目标是让它简单明了,有据可查 尽可能让任何人都可以克隆、启动和继续这个项目,包括直接替换 您的LangGraph可在中运行 graph.py,只需要 useWebSocket.ts 任何前端的实现。

🔍 项目概述

Project Tree
.
├── Dockerfile             # Shipable blueprint Dockerfile
├── Procfile               # web command to run on servers (PaaS eg. Heroku)
├── README.md
├── cust_logger.py         # Custom logger utility for logging for backend serving
├── frontend
│   ├── package.json       # Contains metadata and dependencies for React project
│   ├── public             # Default Create-React-App Public assets
│   │   ├── favicon.ico
│   │   ├── index.html
│   │   ├── logo192.png
│   │   ├── logo512.png
│   │   ├── manifest.json
│   │   └── robots.txt
│   ├── src                # Source code for the React frontend
│   │   ├── App.css
│   │   ├── App.tsx        # Main App component in TypeScript
│   │   ├── components     # Demo components used in App.tsx
│   │   │   └── easter_egg # ssshhhh... try chatting "LangChain"
│   │   │       ├── ee.css
│   │   │       └── ee.tsx
│   │   ├── index.tsx      # Entry point for the React app
│   │   ├── react-app-env.d.ts # Default from Create-React-App
│   │   └── services
│   │       └── useWebSocket.ts # WebSocket hook for real-time communication via WebSocket
│   └── tsconfig.json      # TypeScript configuration for the frontend
├── graph.py               # Simple LangGraph implementation
├── requirements.txt       # Python dependencies required for the backend project
├── server.py              # FastAPI implementation
└── start-local.sh         # Shell script to start the application locally (backend or frontend)

📡 沟通

WebSocket连接允许React前端之间的实时双向通信 FastAPI后端服务器持续接收消息,无需重新加载或重复请求。 有很多方法可以处理发送的数据。这可能是消息本身,一大块消息 (msg_history),或结构化格式。我选择使用结构化格式,因为它允许客户端 并且服务器期望特定顺序的某些密钥,并为未来添加到有效载荷提供灵活性。 我选择使用JSON,因为它最容易阅读和使用,但你可以自由使用其他格式,如XML, YAML、CSV、协议缓冲区(Protobuff)或BSON。简而言之,双方都有一个预定义的JSON结构 正在寻找。如果在交换过程中,无论是前端还是后端,都满足某些条件,它将触发 在特定方面采取行动。例如,如果事件类型为 on_chat_model_stream,它应该流 对客户的回应。或者,如果客户端在套接字连接中收到任何更改,它将进行调整和 相应地渲染或记录。

我们的沟通交流: 从代码库中的注释中了解更多关于每个函数的作用,或者在 演示.

🖥️ 前端

前端有一些功能可以启动:

  • 您可以通过指示器知道您已连接到服务器。
  • 使用多行打字(Shift + Enter)和正常 Enter 发送消息的键。
  • 生成响应时会自动滚动。
  • 如果服务器停机,WebSocket会自动重试重新连接和消息传递。
  • 前端是无状态的,这意味着消息不会存储在前端,而是作为 msg_history;只发送一条消息。
  • 关于如何使用自定义LangGraph事件触发前端组件的说明:
    • 试着向模型询问LangChain或LangGraph!D

🛠️ 后端

我试图在保持功能的同时保持后端非常纤薄。它使用FastAPI和Uvicorn来处理异步请求。一些功能包括:

  • 简单的FastAPI实现

    • 提供从生成的静态web文件 npm build.
    • 允许灵活性 React Router.
    • 提供简单的WebSocket连接。
  • 表达性测井

    • 匹配Uvicorn的日志格式。
    • 使用 file_name:line_num 格式便于日志跟踪。
    • 支持自定义日志颜色,允许您在任何文件中设置相应的颜色。
    • 日志示例:
      INFO:     server.py:34    - {"timestamp": "YYYY-MM-DDTHH:MM:SS.MS", "uuid": "nearer-zebra-one-worker", "received": {"uuid": "oldest-honor-create-card", "message": "what is e?", "init": false}}
      INFO:     graph.py:86     - {"timestamp": "YYYY-MM-DDTHH:MM:SS.MS", "uuid": "nearer-zebra-one-worker", "llm_method": "on_chat_model_end", "sent": "2.718281828459045"}
      
    • JSON中一致的日志格式和输出允许轻松导入任何可观察性系统,由时间序列中的时间戳、会话UUID或LLM函数调用指定。
    • 日志演示
  • 简单图形

    • 此图示例是一个没有工具调用的通用调用模型,但可以很容易地用您自己的图替换。
    • 为简单起见,它目前使用会话UUID来指定线程 内存持久性 使用内存保护程序。
    • 这允许在后端的WebSocket通道中维护会话历史,确保客户端在数据丢失或刷新时不会被定制为渲染和存储。
  • 事件处理器

    • 将WebSocket响应发送回指定的客户端。
    • 目前,您可以在图形中处理聊天流和自定义事件,例如触发前端组件或标志,使用 adispatch_custom_event 和 astream_events.

🚀 让我们运行它

🤖 自动运行

我试图在本地尽可能简单地进行设置和运行 此脚本用于启动应用程序的前端和后端。它接受各种命令行选项来控制要运行的组件及其各自的配置。

在开始之前,请确保 pip install -r requirements.txt,我建议使用你个人风格的虚拟环境,由于用户的假设,我没有自动设置pip。

# required libraries
fastapi              # Fast web framework to handle our APIs
uvicorn              # ASGI server for serving FastAPI applications
websockets           # core WebSocket server and client library
python-dotenv        # reads key-value pairs from a `.env` file and sets them as environment variables
langchain-openai     # LangChain x OpenAI's implementation to use OpenAI's ChatModel within Langchain ecosystem
langgraph            # An awesome talking parrot that shoots webs :D
colorama             # used for coloring logs

./start-local.sh 选项

请阅读 start-local.sh 了解后台运行的别名命令。

重要:您不能使用 --frontend 和 --backend 同时。

  • --frontend:

    • 启动前端应用程序。
    • 例子:
      ./start-local.sh --frontend
      
  • --backend:

    • 默认情况下,启动后端应用程序并在启动后端之前构建前端。
    • 例子:
      ./start-local.sh --backend
      
  • --nobuild 可选标志:

    • 在开始后端之前跳过构建前端。此选项仅在启动后端时相关。
    • 例子:
      ./start-local.sh --backend --nobuild
      
  • --frontend-port <port> 可选标志:

    • 指定前端应用程序应在其上运行的端口。默认端口为 3000.
    • 例子:
      ./start-local.sh --frontend --frontend-port 4000
      
  • --backend-port <port> 可选标志:

    • 指定后端应用程序应在其上运行的端口。默认端口为 8000.
    • 例子:
      ./start-local.sh --backend --backend-port 9000
      
  • 使用限制:

    • 这 --frontend 和 --backend 选项不能一起使用。
    • 请选择一个,然后打开一个新终端,用另一个终端运行脚本。
    • 这是由于重叠的阻塞客户端和服务器控制台,您可以将它们放在后台,但这会变得很麻烦 kill $PID 在开发工作流程中。

🖐 ️手动启动应用程序

如果您不想使用 start-local.sh 脚本,您可以使用以下步骤手动启动前端和后端组件。 我建议使用2个不同的终端选项卡。

  • 对于 前端,导航到 frontend 目录并安装所需的包,然后使用您喜欢的node包管理器运行:
    cd frontend
    npm install
    npm run
    
  • 对于 后端,位于项目文件夹的根目录中。
    pip install -r requirements.txt
    cd frontend
    npm install
    npm build
    cd ..
    uvicorn server:app --host 0.0.0.0 --port 8000 --reload
    

🎥 演示

正如我们在上面看到的,即使两个人在托管服务器上打字,它也可以以非阻塞的方式处理它 并且在不损失响应吞吐量的情况下为两个客户端提供服务。

下面是它从服务器上看起来的样子,可能不是RGB格式:D

🚢 部署

有一个Dockerfile和一个Procfile;两者都可以用于将服务器作为独立的Docker容器运行,或者 在您的解决方案中。我建议使用Docker Compose,通过Helm charts在Kubernetes上轻松部署, 以及用于创建具有VTCL/HZTL缩放的简单副本。如果您的解决方案需要处理端口和SSL 需要它。

注意:此服务器的后端不安全。 由于localhost是HTTP,它目前没有使用WebSocket Secure 以及缺乏便于本地运行的核心安全功能。

我建议在前端添加这样的内容:

const wsProtocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
const wsUrl = `${wsProtocol}://${window.location.hostname}/ws`;

此外,我建议对传入的服务器请求进行原产地检查,并使用JWT令牌保护您的API, OAuth的承载令牌、API密钥等。还可以考虑对WebSocket连接和处理实施速率限制 安全地重新连接,作为防止DDoS攻击的预防措施。

💡 思考与未来改进

这是一个有趣的实现,将两种你想一起使用但没有明确定义的技术混合在一起, 尤其是在两者都可以很好地利用而彼此不受限制的情况下。

可以做出许多改进,但这些改进并不是为了保持简单性和避免潜在的 为未来的用户锁定。我愿意为不同的用例创建一个新模板或添加到这个存储库中, 可能包括:

  • 工具调用可以通过LangGraph中的任何图实现,但它不是作为前端可视化更新处理的。
  • 存储在内存中的对话可以从专用的网络数据库解决方案中受益。
  • 共享对话或通过对话ID查找对话。
  • 按用户处理对话分组需要对用户进行某种形式的区分。

以下是我希望在未来做出的改进:

  • 前端和后端测试
  • Kubernetes(K8s)Docker Compose设置
  • 如果后端太大,可能会把它放在一个文件夹里
  • 移动到vite模板,因为这是FE前进的方向