vllm 部署 GLM-4.7
·
读这篇文章假设已经读过大模型部署
部署一下 GLM-4.7-Flash
https://huggingface.co/zai-org/GLM-4.7-Flash
首先,准备 vllm 环境,vllm 是大模型推理的框架之一。
环境准备
venv、pip、vllm
# 安装 venv
sudo apt install python3-venv -y
# 初始化 venv 环境
python3 -m venv vllm-env
cd vllm-env/
source vllm-env/bin/activate
pip install --upgrade pip
# 安装 vllm,后面要使用 vllm 作为模型推理使用 GLM-4.7 权重
pip install vllm
# ... ... 等待下载后出现 Successfully installed ... 安装完成
# 检测是否可用 https://docs.vllm.ai
vllm -h
下载GLM-4.7-Flash
# 配置镜像站,如果已科学可忽略
export HF_ENDPOINT=https://hf-mirror.com
# 开启多线程下载
export HF_XET_HIGH_PERFORMANCE=1
hf download zai-org/GLM-4.7-Flash
默认下载路径
du -s -h ~/.cache/huggingface/hub/models--zai-org--GLM-4.7-Flash/
59G /root/.cache/huggingface/hub/models--zai-org--GLM-4.7-Flash/
启动GLM-4.7-Flash
启动命令
可以尝试先启动,如果有环境问题往下看
我有两张显卡,这里配置 --tensor-parallel-size 2
显存不多,限制了context --max-model-len 32768
参数作用文末有写
–reasoning-parser glm45
–tool-call-parser glm47
–enable-auto-tool-choice
vllm serve zai-org/GLM-4.7-Flash \
--host 0.0.0.0 \
--port 8099 \
--tensor-parallel-size 2 \
--max-model-len 32768 \
--gpu-memory-utilization 0.9 \
--served-model-name glm-4.7-flash
近60G 的模型启动需要几分钟,日志中看到相关的 starting server 标识 则启动成功。
APIServer pid=1034591) INFO 06-02 19:34:03 [api_server.py:596] Starting vLLM server on http://0.0.0.0:8099
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:37] Available routes are:
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /openapi.json, Methods: HEAD, GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /docs, Methods: HEAD, GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /docs/oauth2-redirect, Methods: HEAD, GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /redoc, Methods: HEAD, GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /tokenize, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /detokenize, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /load, Methods: GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /version, Methods: GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /health, Methods: GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /metrics, Methods: GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/models, Methods: GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /ping, Methods: GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /ping, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /invocations, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/chat/completions, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/chat/completions/batch, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/responses, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/responses/{response_id}, Methods: GET
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/responses/{response_id}/cancel, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/completions, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/messages, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/messages/count_tokens, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /inference/v1/generate, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /scale_elastic_ep, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /is_scaling_elastic_ep, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /generative_scoring, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/chat/completions/render, Methods: POST
(APIServer pid=1034591) INFO 06-02 19:34:03 [launcher.py:46] Route: /v1/completions/render, Methods: POST
(APIServer pid=1034591) INFO: Started server process [1034591]
简单验证
查看模型列表
curl --noproxy '*' http://127.0.0.1:8099/v1/models
请求返回
{
"object": "list",
"data": [
{
"id": "glm-4.7-flash",
"object": "model",
"created": 1780401515,
"owned_by": "vllm",
"root": "zai-org/GLM-4.7-Flash",
"parent": null,
"max_model_len": 32768,
"permission": [
{
"id": "modelperm-8aaff353c7c2a8da",
"object": "model_permission",
"created": 1780401515,
"allow_create_engine": false,
"allow_sampling": true,
"allow_logprobs": true,
"allow_search_indices": false,
"allow_view": true,
"allow_fine_tuning": false,
"organization": "*",
"group": null,
"is_blocking": false
}
]
}
]
}
QA
stream 可以指定为 true,最终他的返回结果与 ollama 有一些差异,返回的结构是 openApi 格式
curl --noproxy '*' http://127.0.0.1:8099/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "glm-4.7-flash",
"messages": [
{"role": "user", "content": "你好,请用三句话介绍你自己"}
],
"stream": false
}'
返回
{
"id": "chatcmpl-8a9c21acdfd79df3",
"object": "chat.completion",
"created": 1780401656,
"model": "glm-4.7-flash",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1. **识别用户的核心请求:**用户希望我(AI)用三句话介绍我自己。\n\n2. **分析约束条件:**\n * 主题:自我介绍(AI助手/LangGPT)。\n * 格式:正好三句话。\n * 语言:中文(提示词的暗示)。\n\n3. **起草初步构思(内心独白/尝试):**\n * *草稿 1:* 我是一个由Z.ai开发的AI语言模型。我可以回答问题和生成文本。我希望通过交流帮助到你。(很好,标准,准确)。\n * *草稿 2:* 你好,我是GLM,一个大型语言模型。我没有情感但我可以处理信息。如果你想聊天或者需要帮助,随时叫我。(稍微随意一点)。\n * *草稿 3:* 我是GLM,一个由智谱AI训练的大语言模型。我可以协助你解答问题、创作内容或进行各种语言交流。很高兴能通过文字与你对话,期待为你提供帮助。(礼貌且专业)。\n\n4. **选择最佳方案:**草稿 3 平衡了身份、功能和建议的行动。简单直接。\n\n5. **润色选定的方案(中文):**\n * 第1句:我是由Z.ai训练的大语言模型,名为GLM。(我是一名由Z.ai训练的语言模型,名字叫GLM。)\n * 第2句:我可以回答问题、撰写文案,并进行各类语言交流。(我可以回答问题、撰写文案,并参与各种语言交流。)\n * 第3句:很高兴能为您提供帮助,请随时告诉我您想知道什么。(很高兴能为您提供帮助,请随时告诉我您想知道什么。)\n\n6. **最终润色(对照约束条件检查):**\n * 是否有三句话?是。\n * 是否为自我介绍?是。\n * 语言是否自然?是。\n\n7. **生成最终输出:**(清晰地呈现句子)。\n\n 我是Z.ai训练的大语言模型GLM。我可以回答问题、撰写文案,并参与各类语言交流。很高兴能为您提供帮助,请随时告诉我您想知道什么。</think>我是Z.ai研发的大语言模型GLM。我可以回答问题、撰写文案,并参与各类语言交流。很高兴能为您提供帮助,请随时告诉我您想知道什么。",
"refusal": null,
"annotations": null,
"audio": null,
"function_call": null,
"tool_calls": [],
"reasoning": null
},
"logprobs": null,
"finish_reason": "stop",
"stop_reason": 154827,
"token_ids": null,
"routed_experts": null
}
],
"service_tier": null,
"system_fingerprint": "vllm-0.22.0-tp2-5b0f4813",
"usage": {
"prompt_tokens": 13,
"total_tokens": 497,
"completion_tokens": 484,
"prompt_tokens_details": null
},
"prompt_logprobs": null,
"prompt_token_ids": null,
"prompt_text": null,
"kv_transfer_params": null
}
环境问题解决
# 这里遇到了一堆环境问题,最终解决办法是将错误贴给 codex 后给出修复命令
# 修复环境后要清掉之前用错误 CUDA 编译过的缓存,然后重新启动 vLLM:
######### rm -rf /root/.cache/flashinfer #########
pip install nvidia-cuda-nvcc-cu12==12.4.131 \
-i https://mirrors.aliyun.com/pypi/simple \
--trusted-host mirrors.aliyun.com
# 依旧是修复环境问题
pip install -U nvidia-cuda-nvcc nvidia-cuda-runtime nvidia-cuda-nvrtc nvidia-cuda-cupti \
-i https://mirrors.aliyun.com/pypi/simple \
--trusted-host mirrors.aliyun.com
export VLLM_USE_FLASHINFER_SAMPLER=0
pip install -U --force-reinstall 'cuda-toolkit[nvcc,nvrtc,cudart,cupti]==13.0.2' \
-i https://mirrors.aliyun.com/pypi/simple \
--trusted-host mirrors.aliyun.com
# 配置 nvcc 环境变量
find /root/vllm-env/vllm-env/lib/python3.12/site-packages/nvidia -name nvcc -type f
find /root/vllm-env/vllm-env/lib/python3.12/site-packages/nvidia -name cuda_runtime.h -type f
find /root/vllm-env/vllm-env/lib/python3.12/site-packages/nvidia -name libcudart.so* -type f
/root/vllm-env/vllm-env/lib/python3.12/site-packages/nvidia/cu13/bin/nvcc
/root/vllm-env/vllm-env/lib/python3.12/site-packages/nvidia/cu13/include/cuda_runtime.h
/root/vllm-env/vllm-env/lib/python3.12/site-packages/nvidia/cu13/lib/libcudart.so.13
export CUDA_HOME=/root/vllm-env/vllm-env/lib/python3.12/site-packages/nvidia/cu13
export PATH="$CUDA_HOME/bin:$PATH"
export CPATH="$CUDA_HOME/include"
export LIBRARY_PATH="$CUDA_HOME/lib"
export LD_LIBRARY_PATH="$CUDA_HOME/lib"
# 检查环境版本
which nvcc
nvcc --version
python -c "import torch; print(torch.__version__, torch.version.cuda)"
/root/vllm-env/vllm-env/lib/python3.12/site-packages/nvidia/cu13/bin/nvcc
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2025 NVIDIA Corporation
Built on Wed_Aug_20_01:58:59_PM_PDT_2025
Cuda compilation tools, release 13.0, V13.0.88
Build cuda_13.0.r13.0/compiler.36424714_0
2.11.0+cu130 13.0
# 版本对齐
torch: 2.11.0+cu130
torch CUDA: 13.0
nvcc: 13.0
参数补充
–reasoning-parser glm45
–tool-call-parser glm47
–enable-auto-tool-choice
这三个参数都是 vLLM 的 OpenAI-compatible API 输出解析/工具调用相关参数,不是模型加载必需参数。
--reasoning-parser glm45
作用:把模型输出里的“思考过程”解析成 OpenAI 风格的 reasoning 字段。
有些 reasoning 模型会输出类似:
<think>这里是思考过程</think>
最终答案
或者厂商自定义的 thinking 格式。
--reasoning-parser glm45 告诉 vLLM:
按 GLM-4.5/GLM 系列的 reasoning 格式去解析模型输出
理想情况下返回会类似:
{
"message": {
"content": "最终答案",
"reasoning": "中间思考过程"
}
}
但如果模型本次没有按 parser 期望的格式输出,vLLM 就解析不出来,reasoning 可能还是 null,思考文本会混在 content 里。
--tool-call-parser glm47
作用:解析 GLM-4.7 的工具调用格式。
比如你给模型传 tools:
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"parameters": {...}
}
}
]
模型可能会生成一段它自己的工具调用文本。
--tool-call-parser glm47 负责把这段文本转换成标准 OpenAI-compatible 的:
"tool_calls": [
{
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{...}"
}
}
]
如果不加这个 parser,模型可能仍然会输出工具调用内容,但它可能只是普通文本,不会变成标准 tool_calls 字段。
--enable-auto-tool-choice
作用:允许模型自动决定是否调用工具。
OpenAI-compatible API 里有:
"tool_choice": "auto"
意思是:
模型自己判断这次要不要调用工具
vLLM 默认不一定允许自动工具选择,所以要加:
--enable-auto-tool-choice
通常它要和:
--tool-call-parser glm47
一起使用。
三者关系
--reasoning-parser glm45
负责解析“思考过程”
--tool-call-parser glm47
负责解析“工具调用”
--enable-auto-tool-choice
允许模型自动选择工具调用
它们不会显著改变模型能力,主要影响 API 返回结构。
你现在的情况是:
模型会输出分析过程
但 reasoning 字段是 null
说明模型输出没有匹配 glm45 parser 期望的 reasoning 格式,或者当前调用方式没有触发独立 reasoning 格式。
更多推荐
所有评论(0)