
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 WorkerFastChat 的默认 Workerfastchat.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即可接入整个集群。安装与启动第一步安装 vLLMpip 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 错误显式指定一个兼容的 tokenizerpython3 -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、提升吞吐但过高可能 OOMvLLM 透传参数—经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 --head与CUDA_VISIBLE_DEVICES指定卡号这在 local_cluster.md 的集群示例中有完整体现例如 33B 模型用--num-gpus 2双卡启动。引擎构建与 Worker 初始化启动流程在if __name__ __main__中完成解析参数 → 构建AsyncLLMEngine→ 创建VLLMWorker→ 用 uvicorn 挂载 FastAPI 应用。VLLMWorker.__init__中有几处关键处理见 vllm_worker.py L31-L65tokenizer 版本兼容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.tokenizervLLM 0.2.7 之后引入了TokenizerGroup包装层源码通过hasattr探测并在必要时剥出内部的 raw tokenizer。这解释了为什么文档建议tokenizer 报错时指定--tokenizer——本质是让引擎拿到的 tokenizer 与generate_stream中的decode/eos_token_id调用兼容。上下文长度上报self.context_len get_context_length(llm_engine.engine.model_config.hf_config)get_context_length 会按max_position_embeddings、max_sequence_length、seq_length、max_seq_len、model_max_length的优先级从 HF 配置中取值并乘以rope_scaling因子取不到时回退为 2048。该值通过/model_details接口对外暴露供上层如 OpenAI API 服务判断请求长度是否超界。注册与心跳若未指定--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 视角下的身份格式一致。生成流程源码解析采样参数如何映射到 vLLMgenerate_stream是 vLLM Worker 的核心方法它接收 Controller 路由过来的请求参数并转写为 vLLM 的SamplingParams。参数默认值与处理逻辑如下见 vllm_worker.py L67-L118请求参数默认值处理逻辑temperature1.0若 1e-5即贪心解码强制top_p 1.0top_p1.0下限钳制为max(top_p, 1e-5)避免 vLLM 因top_p0报错top_k-1.0原样传入presence_penalty0.0原样传入frequency_penalty0.0原样传入max_new_tokens256映射为max_tokensstop/stop_token_ids无见下方 stop 处理echoTrue为 True 时输出拼接 prompt 全文与model_worker行为对齐use_beam_searchFalse原样传入best_ofNone原样传入stop 条件的双重处理是一个易被忽略的细节字符串形式的 stopstop_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: continueis_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_reason为None的空内容消息、再 yield 携带真实finish_reason的最终消息目的是对齐model_worker的流式协议从而让上层的 OpenAI 兼容 APIopenai_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.pyPOST /model_details返回上下文长度并发控制沿用基类的信号量模式acquire_worker_semaphore在入口处以--limit-worker-concurrency默认 1024为上限获取asyncio.Semaphore。vllm_worker.py相对基类的一个增强是create_background_tasks(request_id)——流式请求结束后后台任务不仅释放信号量还会追加执行engine.abort(request_id)确保异常路径下 vLLM 引擎侧的请求也能被显式取消。值得对比的是默认model_worker的ModelWorker.__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_DEVICES0 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_DEVICES2,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 2tokenizer 不匹配时显式指定Llama-2 / guanaco 等模型CUDA_VISIBLE_DEVICES0 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并存由controller与openai_api_server统一对外服务各 Worker 按--port 40000i分配端口。常见问题与注意事项tokenizer 报错不同来源的 LLaMA 系权重常缺少自带 tokenizer按文档指定--tokenizer hf-internal-testing/llama-tokenizer或对应尺寸的 Llama tokenizer见 local_cluster.md。显存不足调低--gpu_memory_utilization默认 0.9其权衡关系KV cache 大小 vs OOM 风险直接写在参数 help 中。想脱离 Controller 单独调试 Worker使用--no-register跳过注册与心跳线程直接对该 Worker 的/worker_generate_stream端点发请求即可。对外模型名--model-names是逗号分隔的显示名用于 Gradio 下拉框与 OpenAI API 的model字段不指定时取--model-path的末段。版本前提本文所有参数与行为以当前仓库代码为准vllm_worker.py对 vLLM 0.2.7 的TokenizerGroup做了兼容实际部署时 vLLM 版本还需满足所加载模型的要求。验证连通性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),仅供参考