FastChat Web 服务端生产部署指南:Controller、Worker 与多标签 Gradio Arena 服务搭建
【免费下载链接】FastChatAn open platform for training, serving, and evaluating large language models. Release repo for Vicuna and Chatbot Arena.项目地址: https://gitcode.com/GitHub_Trending/fa/FastChat
FastChat 提供了一整套面向大规模语言模型对话服务的前后端组件。本文基于仓库内 docs/commands/webserver.md 这一份生产部署备忘,结合 fastchat/serve/ 下的源码实现,系统讲解如何安装环境、逐层启动 Controller 与各类 Worker、拉起带多标签(Arena 对战、单模型直聊、Leaderboard 等)的 Gradio Web 服务,并完成端口监听检查、进程文件句柄上限调优与 Gradio 前端页面定制。读者完成后,可独立复现一个面向内网或外网的 Chatbot Arena 式 Web 服务集群。
1. 部署形态与角色分工
在动手执行命令前,先明确本文部署脚本背后的进程模型。从 docs/server_arch.md 与 fastchat/serve/ 目录可以确认 FastChat 服务端由三类角色构成:
- Controller(调度中枢):维护所有 Worker 的注册表,提供心跳检查、模型列表查询与请求分发。fastchat/serve/controller.py 中
Controller类维护worker_info(Worker 名到WorkerInfo的映射),并支持lottery与shortest_queue两种分发策略(controller.py)。 - Model Worker(算力执行者):真正持有模型权重或调用远程推理 API,向 Controller 注册自身,并通过 FastAPI 暴露
worker_generate_stream等端点。同一模型可注册多个 Worker 以扩展吞吐。 - Web Server(用户入口):基于 Gradio 构建的浏览器界面,向 Controller 拉取模型列表并转发用户请求。fastchat/serve/gradio_web_server_multi.py 实现了带多个 Tab 的 Arena 界面,是本文部署的主角。
原文档中的部署脚本把日志按进程拆到fastchat_logs/controller、fastchat_logs/server0…serverN等独立目录下,便于逐个进程隔离排查,这是一套典型的多机/多进程生产排布,下面按安装、启动、验收的顺序展开。
2. 环境安装与依赖准备
原文档给出的安装流程面向 Ubuntu 系统,核心步骤是安装系统工具、准备 conda 环境并执行 FastChat 的可编辑安装:
sudo apt update sudo apt install tmux htop wget https://repo.anaconda.com/archive/Anaconda3-2022.10-Linux-x86_64.sh bash Anaconda3-2022.10-Linux-x86_64.sh conda create -n fastchat python=3.9 conda activate fastchat git clone https://gitcode.com/GitHub_Trending/fa/FastChat.git cd FastChat pip3 install -e .补充说明几点,便于你按实际情况调整:
python=3.9是原脚本选定的解释器版本;conda 环境名与 Python 版本都可按本机情况替换,后续所有启动命令都依赖当前 conda 环境处于激活状态。- 使用
pip3 install -e .(可编辑安装)而不是普通安装,是因为后续要频繁改动、调试仓库代码,可编辑模式保证改完即生效,无需重装。 - 进入虚拟环境后,
python3应指向~/anaconda3/envs/fastchat/bin/python,可通过which python3验证。 tmux、htop用于把每个服务放进独立会话并实时观察 CPU / 内存,防止服务随 SSH 断开而终止;也可以改用nohup ... &或 systemd 单元来托管进程。
3. 启动 Controller 并注册首个 Worker
3.1 启动 Controller
Controller 是集群的核心注册中心,第一个启动:
cd fastchat_logs/controller python3 -m fastchat.serve.controller --host 0.0.0.0 --port 21001从源码看,create_controller()定义的默认参数为--host localhost、--port 21001(controller.py)。部署到公网或跨机场景时必须显式指定--host 0.0.0.0,让其他机器上的 Worker 与 Web Server 能访问;--dispatch-method默认是shortest_queue(选择queue_length / speed最小的 Worker),也可切换为lottery按速度加权随机分发(controller.py)。心跳相关阈值由环境变量控制:CONTROLLER_HEART_BEAT_EXPIRATION默认 90 秒、WORKER_HEART_BEAT_INTERVAL默认 45 秒(constants.py),即超过 90 秒未收到心跳的 Worker 会被自动清理(controller.py)。
3.2 手动注册 Worker
正常情况下 Worker 启动时会自动向 Controller 注册;register_worker用于手动补注册一个尚未在 Controller 注册表中出现、或不走自动注册流程的 Worker 地址:
python3 -m fastchat.serve.register_worker --controller http://localhost:21001 --worker-name https://观察 fastchat/serve/register_worker.py 的调用逻辑可以推断:该工具会把worker_name连同check_heart_beat、multimodal字段 POST 到 Controller 的/register_worker接口,worker_status传None表示让 Controller 主动回查 Worker 的/worker_get_status获取模型列表(register_worker.py)。原文档示例中的--worker-name https://是内网部署时的示意占位地址,实际应替换为可被 Controller 访问到的完整 Worker 地址,例如http://worker-host:21002。
3.3 发送测试消息验证通路
注册完成后,用test_message向 Controller 查询指定模型对应的 Worker 地址并真正发起一次流式推理,验证整条链路可用:
python3 -m fastchat.serve.test_message --model vicuna-13b --controller http://localhost:21001从 fastchat/serve/test_message.py 的main()可以看到它做的事情非常典型:
- 依次 POST
/refresh_all_workers(触发 Controller 重新校验所有 Worker)与/list_models,打印当前已注册模型列表(test_message.py); - POST
/get_worker_address拿到承载该模型的 Worker 地址(test_message.py); - 使用
get_conversation_template(model_name)构建对话模板,向 Worker 的/worker_generate_stream发起流式请求并按\0分隔符逐块打印生成结果(test_message.py)。
命令默认--temperature 0.0、--max-new-tokens 32,若 Worker 就绪,终端会看到逐字输出的回复;若输出No available workers for xxx,说明该模型尚未被任何 Worker 注册,应优先排查 Worker 侧。
4. 启动模型 Worker(HuggingFace 推理端点版)
原文档中启动的huggingface_api_worker属于“不本地加载权重、直接调用远程推理端点”的 Worker 形态,适合把 Falcon、Zephyr 等托管在 HuggingFace Inference Endpoints 上的模型接入 Arena:
cd fastchat_logs/server0 python3 -m fastchat.serve.huggingface_api_worker --model-info-file ~/elo_results/register_hf_api_models.json4.1 模型信息文件格式
--model-info-file指向一个 JSON 文件,用于声明每个接入模型的端点与鉴权信息。仓库源码头部给出了完整字段说明(huggingface_api_worker.py):
{ "falcon-180b-chat": { "model_name": "falcon-180B-chat", "api_base": "https://api-inference.huggingface.co/models", "model_path": "tiiuae/falcon-180B-chat", "token": "hf_XXX", "context_length": 2048 }, "zephyr-7b-beta": { "model_name": "zephyr-7b-beta", "model_path": "", "api_base": "xxx", "token": "hf_XXX", "context_length": 4096 } }其中必填字段为model_path、api_base、token、context_length,其余字段可选。从create_huggingface_api_worker()的解析代码看(huggingface_api_worker.py),还支持可选字段model_names(为一个或多个名字,缺省取 key 的最后一段)与conv_template(自定义对话模板),这些信息会被批量构建为HuggingfaceApiWorker实例并一次性注册到 Controller。若某个 key 的model_path为空字符串,则直接以api_base作为推理 URL。
4.2 关键启动参数
该模块的完整参数可通过python3 -m fastchat.serve.huggingface_api_worker --help查看,常用项及默认值如下(huggingface_api_worker.py):
| 参数 | 默认值 | 说明 |
|---|---|---|
--host | localhost | Worker 监听地址 |
--port | 21002 | Worker 监听端口 |
--worker-address | http://localhost:21002 | 注册给 Controller 的对外地址,跨机时须改为可达地址 |
--controller-address | http://localhost:21001 | Controller 地址 |
--model-info-file | 必填 | 上述模型注册 JSON 文件 |
--limit-worker-concurrency | 5 | 并发上限,用于防止打爆远端推理端点(OOM) |
--no-register | 关闭 | 开启后只启动服务、不向 Controller 注册,便于先行联调 |
--seed | None | 覆盖每次生成的随机种子 |
Worker 内部通过huggingface_hub.InferenceClient以流式方式调用text_generation,并把结果按 FastChat 约定逐条序列化后以\0结尾返回(huggingface_api_worker.py)。由于该 Worker 没有本地 tokenizer,count_token直接返回 0(huggingface_api_worker.py),token 统计由调用方决定如何处理。
若希望本地加载权重(Vicuna、Llama 等)而不是走远程 API,应改用
fastchat.serve.model_worker(本地 GPU Worker)或vllm_worker/sglang_worker等高性能后端,可参考 docs/vllm_integration.md 与 docs/sglang 相关文档 了解接入方式。本部署脚本走的是托管端点路径,不需要本地 GPU 常驻显存。
5. 启动多标签 Gradio Web Server
前端是整个部署的门面。原文档在配置好环境变量后启动gradio_web_server_multi,从而获得带 “Arena(对战)”“side-by-side(具名对比)”“Direct Chat(单模型直聊)” 等标签的 Chatbot Arena 界面。
5.1 配置第三方 API 密钥
启动前需要为希望接入的闭源模型准备对应的服务密钥:
export OPENAI_API_KEY= export ANTHROPIC_API_KEY= export GCP_PROJECT_ID=这三项分别对应 OpenAI(ChatGPT)、Anthropic(Claude)与 Google(PaLM/Gemini)三种 API 类模型来源。值得说明的是:API 类模型本身并非由本地 Worker 承载,而是由 Web Server 通过对应的 provider 客户端直接调用官方接口,因而密钥只需在运行 Web Server 的进程环境中配置即可;相关 provider 枚举可见 fastchat/serve/gradio_web_server.py 中对api_type(openai/anthropic/gemini/mistral)的说明。
5.2 启动命令与参数对照
原文档使用的生产启动命令为:
python3 -m fastchat.serve.gradio_web_server_multi \ --controller http://localhost:21001 \ --concurrency 50 \ --add-chatgpt --add-claude --add-palm \ --elo ~/elo_results/elo_results.pkl \ --leaderboard-table-file ~/elo_results/leaderboard_table.csv \ --register ~/elo_results/register_oai_models.json \ --show-terms需要向读者说明:上述命令是原文档部署 Chatbot Arena 站点时的写法,属于该命令的一个较早期版本。对照当前仓库 fastchat/serve/gradio_web_server_multi.py 的argparse定义,CLI 已有较大演进——--add-chatgpt/--add-claude/--add-palm与--concurrency、--register等旧参数不再存在,功能分别由新参数承接。在当前代码上等效的启动方式为:
python3 -m fastchat.serve.gradio_web_server_multi \ --host 0.0.0.0 --port 7860 \ --controller-url http://localhost:21001 \ --concurrency-count 50 \ --register-api-endpoint-file ~/elo_results/register_oai_models.json \ --elo-results-file ~/elo_results/elo_results.pkl \ --leaderboard-table-file ~/elo_results/leaderboard_table.csv \ --show-terms-of-use新参数与旧写法的映射关系及含义如下:
| 旧文档写法 | 当前参数 | 含义 |
|---|---|---|
--concurrency 50 | --concurrency-count 50 | Gradio 队列默认并发上限(默认10) |
--register xxx.json | --register-api-endpoint-file xxx.json | 从 JSON 注册 API 类模型端点 |
--add-chatgpt/--add-claude/--add-palm | (由 register 文件声明) | 决定接入哪些闭源模型 |
--elo xxx.pkl | --elo-results-file xxx.pkl | 加载 ELO 结果并渲染 Leaderboard 图 |
--leaderboard-table-file | --leaderboard-table-file | Leaderboard 表格数据文件 |
--show-terms | --show-terms-of-use | 进入页面前弹出使用条款确认 |
其余在当前源码中仍可用的重要参数还包括:--model-list-mode {once,reload}(默认once,reload表示每次请求都向 Controller 重新拉取模型列表,便于动态增删模型)、--vision-arena(显示多模态对战标签)、--ga-id(Google Analytics 统计 ID,与下方前端定制相呼应)、--gradio-auth-path/--password(认证)、--moderate(开启输入内容审核)与--share(生成公网分享链接)等(gradio_web_server_multi.py)。
API 端点注册文件register_oai_models.json的格式在 gradio_web_server.py 中有明确注释,形如:
{ "gpt-3.5-turbo": { "model_name": "gpt-3.5-turbo", "api_type": "openai", "api_base": "https://api.openai.com/v1", "api_key": "sk-******", "anony_only": false } }api_type可选openai、anthropic、gemini、mistral;anony_only为true时该模型只出现在匿名对战模式中,不进入具名列表。
5.3 服务启动方式与 Leaderboard 数据来源
从 gradio_web_server_multi.py 可以看到,demo.queue(...).launch(...)最终以max_threads=200、show_api=False的方式对外服务;--elo-results-file与--leaderboard-table-file若非空,则会在第三个 Tab 渲染build_leaderboard_tab(monitor.py)。ELO 分数、排行榜 CSV 是对战数据离线计算的产物,生成方法可参考 docs/commands/leaderboard.md;若只是做单机验证,可以不带这两个参数直接启动,此时不会显示 Leaderboard Tab。
5.4 多路并发部署时的日志管理
原文档的生产脚本将每个 Web Server 放进独立目录并各自cd后启动。FastChat 的日志输出目录由LOGDIR环境变量控制,默认是当前目录.(constants.py),因此“每个服务单独cd一个目录”的做法,本质上是为了让各进程的gradio_web_server.log、model_worker_*.log、controller.log等日志文件落到互不干扰的独立目录,便于按服务巡检。实际多副本部署时,可把第 5.2 节的启动命令在fastchat_logs/server1、server2… 等多个目录分别以不同--port拉起,对外由 Nginx 等反向代理做负载均衡(参考 fastchat/serve/gateway/nginx.conf)。
6. 检查服务启动耗时与就绪状态
多副本场景下逐个人眼看日志不现实,原文档给出了一段循环检查命令:遍历server0~server11的日志,抓取每条 Gradio 服务“已监听本地 URL”的最后一行日志,即可快速确认各副本是否全部就绪:
for i in $(seq 0 11); do cat fastchat_logs/server$i/gradio_web_server.log | grep "Running on local URL" | tail -n 1; donegradio_web_server.log由 fastchat/serve/gradio_web_server.py 中的build_logger("gradio_web_server", "gradio_web_server.log")产生,与 Web Server 在同一进程内随logger.info(f"args: {args}")(gradio_web_server_multi.py)记录启动参数。若某一行输出为空,说明对应副本尚未打出监听日志,需要回到该目录查看进程是否存活或端口是否被占用;seq 0 11中的区间应按实际启动的副本数调整。
7. 提高最大打开文件数上限
高并发的 Web 服务(尤其同时维护大量浏览器长连接与上游 Worker HTTP 连接时)很容易触达系统默认的进程文件句柄上限,原文档给出了“单进程免重启”与“系统级持久化”两种处理方式。
方式一:单进程即时调整(无需重启)
先用ps找到目标进程 PID,再用prlimit把该进程的 nofile 上限调高到 1048576:
sudo prlimit --nofile=1048576:1048576 --pid=$id对 Gradio 类 Web 服务进程做批量调整:
for id in $(ps -ef | grep gradio_web_server | awk '{print $2}'); do echo $id; prlimit --nofile=1048576:1048576 --pid=$id; done--nofile=软限:硬限语法分别设定 soft limit(进程可自行调高)与 hard limit(权限上限)。注意该方式只对本次启动的进程生效,进程重启后需重新执行;且对 root 属主之外的进程调整硬限通常需要 root 权限,故示例保留sudo。
方式二:系统级配置(需重启生效)
在/etc/security/limits.conf末尾追加如下两行,对所有用户生效:
* hard nofile 65535 * soft nofile 65535该方式属于 PAMpam_limits机制,作用于后续新登录会话与由其启动的全部进程,修改后需重新登录或重启系统。实践上建议两者结合:limits.conf 保证新进程默认高上限,prlimit用于对存量进程热修复。
8. 前端定制:注入统计脚本与文案优化
原文档针对当时固定版本的 Gradio(3.35.2)记录了若干“改前端文件”的运维技巧,目的是在不改业务代码的情况下完成埋点、加载提示与告警抑制。由于这些修改发生在 Gradio 的 Python site-packages 安装目录内,路径形如/home/vicuna/anaconda3/envs/fastchat/lib/python3.9/site-packages/gradio/...,升级 Gradio 后会被覆盖,请务必把定制项固化为可重复执行的补丁或记录。
8.1 在 index.html 注入 gtag 与 html2canvas
编辑 Gradio 前端模板入口.../site-packages/gradio/templates/frontend/index.html,在<head>中追加 Google Analytics 标签与截图库 html2canvas:
<!-- Google tag (gtag.js) --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-K6D24EE9ED"></script><script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-K6D24EE9ED'); window.__gradio_mode__ = "app"; </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>埋点用于统计页面访问;html2canvas则支撑“把对局结果渲染成图片保存/分享”这类功能。值得一提的是,在当前仓库版本中,这两项能力已经原生内置到业务代码里,不再需要手工改 Gradio 模板:build_demo()会把html2canvas的<script>恒常注入页面头部,并在传入--ga-id时自动拼接 gtag 脚本(gradio_web_server_multi.py)。也就是说,新版本直接传--ga-id G-xxxx即可等价实现上述第 1 步的埋点效果。
8.2 抑制弃用参数告警
编辑.../site-packages/gradio/deprecation.py,找到函数定义:
def check_deprecated_parameters(按需在其内部提前return或注释告警分支,即可屏蔽 Gradio 对旧版调用方式的DeprecationWarning输出。这类告警本身不影响功能,仅在日志里刷屏,是否处理取决于对日志洁净度的要求。
8.3 修改“Loading”提示文案
Gradio 前端资源经打包后位于.../site-packages/gradio/templates/frontend/assets/index-188ef5e8.js(该 hash 文件名会随版本变化)。在 Vim 中用全局替换把默认的“Loading...”改为更友好的引导文案:
%s/"Loading..."/"Loading...(Please refresh if it takes more than 30 seconds)"/g当上游 Worker 冷启动较慢、浏览器长时间停留在加载态时,这条提示能显著降低用户困惑。执行后需清空浏览器缓存并硬刷新(Ctrl+Shift+R)才能看到新文案。
9. 结语与排障速查
本文围绕 docs/commands/webserver.md 还原了一条完整的 FastChat Arena Web 服务生产部署链路:conda 环境与可编辑安装 → Controller(controller.py)→ Worker 注册(register_worker.py)与连通性验证(test_message.py)→ 远程端点型 Worker(huggingface_api_worker.py)→ 多标签 Gradio 门户(gradio_web_server_multi.py),最后覆盖了启动验收、文件句柄上限调优与前端定制三块日常运维动作。当链路不通时,可按下述顺序排查:
- 测试消息返回无 Worker:确认模型名与 Worker 注册的
model_names完全一致,Controller 地址可达,Worker 的--no-register未误开; - Web 页面模型列表为空:检查 Web Server 的
--controller-url,并用model-list-mode reload重新拉取(gradio_web_server_multi.py); - 生成超时/报错:查看对应目录下的
controller.log与gradio_web_server.log,并结合 constants.py 中FASTCHAT_WORKER_API_TIMEOUT(默认 100 秒)等环境变量确认超时窗口是否过短; - 页面加载慢且句柄耗尽:按第 7 节调高
prlimit并检查反向代理的 keep-alive 配置。
对于需要本地 GPU 加载权重的模型,请另行参考 docs/commands/local_cluster.md(多机 Worker 集群)与 fastchat/serve/model_worker.py,它们在 Controller/Web Server 层的接入方式与本文一致,可以无缝混布在同一集群中。
【免费下载链接】FastChatAn open platform for training, serving, and evaluating large language models. Release repo for Vicuna and Chatbot Arena.项目地址: https://gitcode.com/GitHub_Trending/fa/FastChat
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考