news 2026/9/6 21:41:10

FastChat 接入 vLLM:用高吞吐推理引擎替换模型 Worker 的部署实践与源码解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FastChat 接入 vLLM:用高吞吐推理引擎替换模型 Worker 的部署实践与源码解析

FastChat 接入 vLLM:用高吞吐推理引擎替换模型 Worker 的部署实践与源码解析

【免费下载链接】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 官方文档 vLLM Integration 展开,讲清如何在 FastChat 中把默认的 Hugging Face 模型 Worker 替换为 vLLM Worker:从安装、启动命令、tokenizer 兼容与 AWQ 量化等实操细节,到vllm_worker.py的引擎构建、采样参数映射、流式输出与 Controller 注册机制的源码级原理。读完后你可以独立部署一个基于 vLLM 的 FastChat 集群,并理解每个命令行参数在底层如何生效。

为什么要用 vLLM Worker

FastChat 的默认 Worker(fastchat.serve.model_worker)基于 Hugging Face Transformers 加载模型,README 对其定位是:

The default model worker based on huggingface/transformers has great compatibility but can be slow. If you want high-throughput batched serving, you can try vLLM integration.

官方文档给出的核心理由是:vLLM 提供先进的连续批处理(continuous batching),可带来约 10 倍的吞吐提升。vLLM 在此体系中充当可替换的 Worker 实现——它只改变"模型如何被加载和推理"这一层,FastChat 的 Controller、Gradio Web 服务、OpenAI API 服务的命令与用法完全不变。vLLM 自身支持的模型清单以官方支持模型列表为准。

从源码结构看,这一设计成立的关键在于 FastChat 抽出了公共基类 BaseModelWorker,它封装了 Worker 与 Controller 之间的通信协议(注册、心跳、状态查询),而vllm_worker.py只需继承该基类并实现generate_stream即可接入整个集群。

安装与启动

第一步:安装 vLLM

pip install vllm

第二步:用 vLLM Worker 替换普通 Worker

启动模型 Worker 时,把fastchat.serve.model_worker换成fastchat.serve.vllm_worker,其余服务(controller、gradio web server、OpenAI API server)保持原样:

python3 -m fastchat.serve.vllm_worker --model-path lmsys/vicuna-7b-v1.5

第三步(按需):tokenizer 报错与 AWQ 量化模型

若遇到 tokenizer 错误,显式指定一个兼容的 tokenizer:

python3 -m fastchat.serve.vllm_worker --model-path lmsys/vicuna-7b-v1.5 --tokenizer hf-internal-testing/llama-tokenizer

若使用 AWQ 量化模型,加上量化参数:

python3 -m fastchat.serve.vllm_worker --model-path TheBloke/vicuna-7B-v1.5-AWQ --quantization awq

这里有个值得注意的细节:vllm_worker.py自身的argparse并没有定义--tokenizer--quantization参数,它们来自 vllm_worker.py 末尾的这一行:

parser = AsyncEngineArgs.add_cli_args(parser)

即 vLLM 的AsyncEngineArgs会把全部 vLLM 引擎参数--tokenizer--quantization--dtype--max-model-len等)注入 FastChat 的命令行解析器。这意味着凡是 vLLM 引擎支持的选项,都可以直接透传给 vLLM Worker,无需 FastChat 逐个声明。

vLLM Worker 命令行参数详解

以下参数表整理自 vllm_worker.py 的argparse定义,包含默认值:

参数默认值说明
--hostlocalhostWorker 服务监听地址
--port21002Worker 服务端口
--worker-addresshttp://localhost:21002向 Controller 注册的地址,多机部署时需用其他节点可访问的地址
--controller-addresshttp://localhost:21001Controller 地址
--model-pathlmsys/vicuna-7b-v1.5模型路径(本地路径或 Hugging Face 名称)
--model-names无(取 model-path 末段)逗号分隔的对外显示名称,供 Arena/API 侧选择模型
--limit-worker-concurrency1024Worker 侧异步信号量上限,控制并发请求数
--no-register关闭跳过向 Controller 注册(用于独立调试)
--num-gpus1使用的 GPU 数量,大于 1 时映射为张量并行
--conv-template无(按模型自动推断)会话模板名称
--trust_remote_codeTruestore_false下载模型时信任 Hugging Face 远程代码
--gpu_memory_utilization0.9GPU 显存中预留给模型权重、激活与 KV cache 的比例。调高可增大 KV cache、提升吞吐,但过高可能 OOM
vLLM 透传参数AsyncEngineArgs.add_cli_args(parser)注入的全部 vLLM 引擎参数

其中--num-gpus的处理逻辑在 vllm_worker.py 入口处:

if args.model_path: args.model = args.model_path if args.num_gpus > 1: args.tensor_parallel_size = args.num_gpus engine_args = AsyncEngineArgs.from_cli_args(args) engine = AsyncLLMEngine.from_engine_args(engine_args)

也就是说 FastChat 并不直接感知张量并行,只是把--num-gpus转写成 vLLM 的tensor_parallel_size交给引擎自行切分模型。多卡部署时通常还需配合ray start --headCUDA_VISIBLE_DEVICES指定卡号,这在 local_cluster.md 的集群示例中有完整体现(例如 33B 模型用--num-gpus 2双卡启动)。

引擎构建与 Worker 初始化

启动流程在if __name__ == "__main__"中完成:解析参数 → 构建AsyncLLMEngine→ 创建VLLMWorker→ 用 uvicorn 挂载 FastAPI 应用。

VLLMWorker.__init__中有几处关键处理(见 vllm_worker.py L31-L65):

  1. tokenizer 版本兼容
self.tokenizer = llm_engine.engine.tokenizer # This is to support vllm >= 0.2.7 where TokenizerGroup was introduced # and llm_engine.engine.tokenizer was no longer a raw tokenizer if hasattr(self.tokenizer, "tokenizer"): self.tokenizer = llm_engine.engine.tokenizer.tokenizer

vLLM 0.2.7 之后引入了TokenizerGroup包装层,源码通过hasattr探测并在必要时剥出内部的 raw tokenizer。这解释了为什么文档建议"tokenizer 报错时指定--tokenizer"——本质是让引擎拿到的 tokenizer 与generate_stream中的decode/eos_token_id调用兼容。

  1. 上下文长度上报
self.context_len = get_context_length(llm_engine.engine.model_config.hf_config)

get_context_length 会按max_position_embeddingsmax_sequence_lengthseq_lengthmax_seq_lenmodel_max_length的优先级从 HF 配置中取值,并乘以rope_scaling因子,取不到时回退为 2048。该值通过/model_details接口对外暴露,供上层(如 OpenAI API 服务)判断请求长度是否超界。

  1. 注册与心跳:若未指定--no-register,调用基类的init_heart_beat()。BaseModelWorker 会先向 Controller 的/register_worker端点注册自身地址与模型信息,随后启动守护线程按WORKER_HEART_BEAT_INTERVAL(默认 45 秒,可用环境变量FASTCHAT_WORKER_HEART_BEAT_INTERVAL覆盖,见 constants.py)调用/receive_heart_beat上报队列长度;若 Controller 回复exist为假,则自动重新注册。

worker_id并非自己生成,而是直接复用model_worker模块中的全局变量(str(uuid.uuid4())[:8]),保证两种 Worker 在日志与 Controller 视角下的身份格式一致。

生成流程源码解析:采样参数如何映射到 vLLM

generate_stream是 vLLM Worker 的核心方法,它接收 Controller 路由过来的请求参数,并转写为 vLLM 的SamplingParams。参数默认值与处理逻辑如下(见 vllm_worker.py L67-L118):

请求参数默认值处理逻辑
temperature1.0<= 1e-5(即贪心解码),强制top_p = 1.0
top_p1.0下限钳制为max(top_p, 1e-5),避免 vLLM 因top_p=0报错
top_k-1.0原样传入
presence_penalty0.0原样传入
frequency_penalty0.0原样传入
max_new_tokens256映射为max_tokens
stop/stop_token_ids见下方 stop 处理
echoTrue为 True 时输出拼接 prompt 全文(与model_worker行为对齐)
use_beam_searchFalse原样传入
best_ofNone原样传入

stop 条件的双重处理是一个易被忽略的细节:

  • 字符串形式的 stop(stop_str)直接收集为集合;
  • stop_token_ids会被 tokenizer 逐个decode成字符串——若解码结果非空则同时加入字符串 stop 集合,同时原始的stop_token_ids(含自动追加的eos_token_id)也一并传给 vLLM。

这样可以兼容 vLLM 中"token 级 stop"与"字符串级 stop"两种机制,保证特殊 token 与常规文本停止符都能正确截断输出。

流式输出中的 partial stop 过滤

partial_stop = any(is_partial_stop(text_outputs, i) for i in stop) # prevent yielding partial stop sequence if partial_stop: continue

is_partial_stop 检查当前输出末尾是否恰好是某个 stop 串的前缀(例如刚吐出\n而 stop 是\nAssistant),若命中则跳过本次 yield,避免客户端看到半截停止序列。

客户端断连的中止处理:流式循环中每次检查request.is_disconnected(),一旦断连即调用engine.abort(request_id),将finish_reason置为"abort"并结束生成——这意味着被放弃的请求会立即释放 KV cache 资源,而不是跑完整个序列。

双次 yield 的设计

if request_output.finished: yield (json.dumps({**ret, **{"finish_reason": None}}) + "\0").encode() yield (json.dumps(ret) + "\0").encode()

源码注释写明:这里故意在结束时先 yield 一条finish_reasonNone的空内容消息、再 yield 携带真实finish_reason的最终消息,目的是对齐model_worker的流式协议,从而让上层的 OpenAI 兼容 API(openai_api_server.py)能正确发出含finish_reason且内容为空的最后一个 chat completion chunk。

非流式的generate方法则是消费完generate_stream后解析最后一条报文,保证两种接口返回结构一致。

FastAPI 接口与信号量并发控制

vLLM Worker 自身是一个 FastAPI 服务,暴露的端点与BaseModelWorker提供的协议端点完全对应(vllm_worker.pyL198-L241 与 base_model_worker.py L196-L241):

端点作用
POST /worker_generate_stream流式生成,StreamingResponse返回
POST /worker_generate非流式生成
POST /worker_get_status返回模型名与队列长度,供 Controller 调度
POST /count_token统计 prompt token 数
POST /worker_get_conv_template返回会话模板(由--conv-template或按--model-path自动推断,推断逻辑见 model_adapter.py)
POST /model_details返回上下文长度

并发控制沿用基类的信号量模式:acquire_worker_semaphore在入口处以--limit-worker-concurrency(默认 1024)为上限获取asyncio.Semaphorevllm_worker.py相对基类的一个增强是create_background_tasks(request_id)——流式请求结束后,后台任务不仅释放信号量,还会追加执行engine.abort(request_id),确保异常路径下 vLLM 引擎侧的请求也能被显式取消。

值得对比的是默认model_workerModelWorker.__init__支持--load-8bit--cpu-offloading--gptq-config--awq-config--exllama-config等参数(见 model_worker.py L38-L57);而 vLLM Worker 的量化支持统一走 vLLM 引擎自身的--quantization awq等参数,两套机制互不重叠。

多机与多卡部署示例

官方文档 local_cluster.md 给出了在 GPU 集群上以 vLLM Worker 组网的完整示例,摘录几个有代表性的形态:

单卡单 Worker(指定可见设备与独立端口):

CUDA_VISIBLE_DEVICES=0 python3 -m fastchat.serve.vllm_worker --model-path lmsys/vicuna-13b-v1.5 --model-name vicuna-13b --controller http://node-01:10002 --host 0.0.0.0 --port 31000 --worker-address http://$(hostname):31000

双卡张量并行(33B 模型):

CUDA_VISIBLE_DEVICES=2,3 ray start --head python3 -m fastchat.serve.vllm_worker --model-path lmsys/vicuna-33b-v1.3 --model-name vicuna-33b --controller http://node-01:10002 --host 0.0.0.0 --port 31002 --worker-address http://$(hostname):31002 --num-gpus 2

tokenizer 不匹配时显式指定(Llama-2 / guanaco 等模型):

CUDA_VISIBLE_DEVICES=0 python3 -m fastchat.serve.vllm_worker --model-path meta-llama/Llama-2-13b-chat-hf --model-name llama-2-13b-chat --controller http://node-01:10002 --host 0.0.0.0 --port 31000 --worker-address http://$(hostname):31000 --tokenizer meta-llama/Llama-2-7b-chat-hf

跨节点部署的要点:--host 0.0.0.0使 Worker 对外可访问;--worker-address使用$(hostname)让 Controller(位于 node-01)能通过真实主机名回调该 Worker;张量并行的 Worker 需先ray start

测试脚本 tests/launch_openai_api_test_server.py 也演示了混布场景:多个model_worker与一个vllm_workermeta-llama/Llama-2-7b-chat-hf,同样追加--tokenizer hf-internal-testing/llama-tokenizer)并存,由controlleropenai_api_server统一对外服务,各 Worker 按--port 40000+i分配端口。

常见问题与注意事项

  1. tokenizer 报错:不同来源的 LLaMA 系权重常缺少自带 tokenizer,按文档指定--tokenizer hf-internal-testing/llama-tokenizer(或对应尺寸的 Llama tokenizer,见 local_cluster.md)。
  2. 显存不足:调低--gpu_memory_utilization(默认 0.9),其权衡关系(KV cache 大小 vs OOM 风险)直接写在参数 help 中。
  3. 想脱离 Controller 单独调试 Worker:使用--no-register跳过注册与心跳线程,直接对该 Worker 的/worker_generate_stream端点发请求即可。
  4. 对外模型名--model-names是逗号分隔的显示名,用于 Gradio 下拉框与 OpenAI API 的model字段;不指定时取--model-path的末段。
  5. 版本前提:本文所有参数与行为以当前仓库代码为准;vllm_worker.py对 vLLM 0.2.7 的TokenizerGroup做了兼容,实际部署时 vLLM 版本还需满足所加载模型的要求。
  6. 验证连通性:Worker 启动后可用python3 -m fastchat.serve.test_message --model <model-name> --controller http://<controller>:<port>发送测试消息(用法见 local_cluster.md 的 test 一节)。

小结

FastChat 的 vLLM 集成体现了一种典型的"可替换推理后端"架构:BaseModelWorker 固定了注册、心跳、状态与协议接口,vllm_worker.py 只负责把请求参数翻译成 vLLMSamplingParams并驱动AsyncLLMEngine生成。对使用者而言,切换成本只有一行命令(把model_worker换成vllm_worker),换来的是连续批处理带来的吞吐提升;对排查问题而言,tokenizer 兼容、partial stop、断连中止与双次 yield 这四处源码细节,是理解流式行为异常时最应优先检查的位置。

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 21:39:06

教育学硕士亲测:智能排版10分钟搞定论文格式的完整流程

读教育学硕士的第三年&#xff0c;我帮导师整理过十几份学生论文&#xff0c;最深的体会是&#xff1a;内容再好&#xff0c;格式乱了就先输一半。标题字号不统一、图表编号对不上、参考文献一会儿GB/T 7714一会儿自创格式&#xff0c;页眉页码更是重灾区。教育学院的格式细则足…

作者头像 李华
网站建设 2026/9/6 21:37:47

WeKnora 上手实战:5分钟让一份PDF答出答案

WeKnora 上手实战&#xff1a;5分钟让一份PDF答出答案 【免费下载链接】WeKnora Open-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki. 项目地址: https://gitcode.com/GitHub_Trend…

作者头像 李华
网站建设 2026/9/6 21:32:52

PPT Master 使用教程:把文档变成原生可编辑 PPT 的完整方法

PPT Master 使用教程&#xff1a;把文档变成原生可编辑 PPT 的完整方法 【免费下载链接】ppt-master AI turns documents or topics into real, native PowerPoint decks—with native shapes, transitions and animations, data-backed charts and tables on demand, audio na…

作者头像 李华
网站建设 2026/9/6 21:28:54

纯电动汽车能量管理仿真分析:从模型构建到策略验证的关键路径

简介&#xff1a;《纯电动汽车能量管理仿真分析研究.pdf》是一份面向新能源汽车技术研发、汽车专业学习与相关课题参考的PDF研究文献&#xff0c;重点围绕纯电动汽车能量管理策略与仿真分析展开。文档首先梳理了逻辑控制、基于控制策略的功率分配车速控制、全局优化控制及模糊控…

作者头像 李华