在win11的docker部署的dify中调用部署在wsl里的vllm服务
近期好友推荐了一个视频《Cursor手搓性能压测工具实测Ollama与vLLM,性能差距吓死人!》,看了这个对比结果,感觉这白嫖的好事怎么能不参合一下呢?只可惜vllm不能直接部署在windows里,所以要在先搞定wsl,然后再一步步来。
# wsl
在网上找了这篇《windows11 安装WSL2全流程》,感觉已经很全面了,基本上照着做就行了,有以下3点需要注意:
- 内核更新包别用文章中的链接,要么执行:wsl --update,要么在github上下载最新版的安装包
- 导出后换个非系统盘导入是一定要做的,等一系列都装完一看ubuntu的虚拟磁盘文件都已经要20G了。需要注意的是重新导入后默认登录的用户是root,如果要改为安装时自己建的个人用户,建议参考文章直接修改/etc/wsl.conf配置文件,而不是为某个ubuntu发行版配置默认用户
- 如果是用windows terminal来访问wsl,那在导出镜像后unregister命令执行后,记得在windows terminal中把默认的ubuntu配置文件隐藏掉,因为导入后会生成一个新的。如果不把旧的隐藏掉,万一不小心点到旧的,就会在默认系统盘位置再起个ubuntu
# vllm安装
按照《官网手册》,使用预编译的文件安装即可。第一次安装时尝试用cuda12.8,然后全部重新编译安装在执行pip install -e .后就卡住了,只得放弃。有几点心得觉得可以分享一下:
- 使用的wsl ubuntu24.04中没有gcc,所以需要先安装gcc,然后安装cuda 12.1,推荐使用runfile(local),将文件下载到windows的某个路径中,然后在wsl中执行/mnt下对应的路径,以避免虚拟磁盘体积过大。在执行过程中会报gcc版本问题,根据提示加--override参数即可顺利安装
- 如果不想安装conda,可以使用python自带的venv来创建虚拟环境,只是ubuntu24.04中没有pip与venv,需要执行sudo apt install python3-pip python3-venv,安装完成后即可创建虚拟环境,比如:python3 -m pythonvenv ~/pythonvenv
- 为虚拟环境配置pip国内源,以配置清华源为例,可以先进入虚拟环境:source ~/pythonvenv/bin/activate,然后执行:pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
- 在虚拟环境下先手动安装pytorch,注意最新版pytorch没有cuda12.1,所以需要安装旧版本,比如2.5.1,执行命令:pip install torch==2.5.1 torchvision==0.20.1 torchaudio==2.5.1 --index-url https://download.pytorch.org/whl/cu121
- 最后根据官网手册,在虚拟环境执行:pip install vllm 即可完成安装
# vllm运行
首先要解决模型的问题,如果使用modelscope上下载的原始模型,2080TI魔改的22G显存也只能跑7B模型,故还是使用ollama下载已经量化好的模型,参考这2篇文章:《使用ollama导出gguf模型》、《Docker + vLLM 部署DeepSeek R1-Distill-Qwen-32B-GGUF量化版本》,以最近新出的QwQ-32b模型为例,可以按如下思路把vllm运行起来:
- 运行ollama run qwq,待下载完成后运行ollama list,可以看到对应的模型名为qwq:latest,然后执行ollama show --modelfile qwq:latest,可以找到模型文件名,然后把这个文件复制到自己存放模型的目录,此处模型最终复制后的完整路径为:E:\model\QwQ-32B-light\QwQ-32B-light.gguf
- 到modelscope上找到通义千问 QwQ-32B模型,在模型文件页下载3个文件:config.json、tokenizer.json、tokenizer_config.json,放到E:\model\QwQ-32B-light目录下
- 在虚拟环境中执行:python3 -m vllm.entrypoints.openai.api_server --model /mnt/e/model/QwQ-32B-light/QwQ-32B-light.gguf --tokenizer /mnt/e/model/QwQ-32B-light --served-model-name QwQ-32B-light --dtype=half --api-key token-abc123 --max_model_len 4096 --gpu_memory_utilization 0.98 --trust-remote-code --enforce_eager (注:--api-key需要改成自己定义的)
- 看一下前一条命令执行有没有报错,要是没有的话,观察显存使用量是不是上去了。因为--gpu_memory_utilization 0.98,所以显存应该基本占满了。最后命令行里会有提示服务运行成功。
- 在虚拟环境中运行如下python脚本,要是运行有返回就说明vllm服务正常了。
from openai import OpenAI
openai_api_key = "token-abc123"
openai_api_base = "http://localhost:8000/v1"
client = OpenAI(
api_key=openai_api_key,
base_url=openai_api_base,
)
chat_response = client.chat.completions.create(
model="QwQ-32B-light",
messages=[
{"role": "user", "content": "你好"},
]
)
print("Chat response:", chat_response)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 配置dify模型提供商
windows下的dify使用docker方式安装,由于已经配置过wsl,就只需从docker desktop官网下载安装即可,但需要注意因为使用的是wsl所以一样是建议不要放在系统盘,docker的好处在于在选项里可以直接改而不需要自己用命令的方式去调整,在settings-Resources-Advanced中调整Disk Image Location
dify使用开源版本进行安装,由于涉及拉取docker镜像,需要自行解决网络问题。
由于在windows下安装在ubuntu中的vllm与docker中的dify分别属于2个系统,网络是隔离的,故需要windows作为宿主机进行转发,参考这篇文章《同一局域网下windows主机和wsl子系统相互网络服务访问》,按如下步骤操作:
- 在wsl的ubuntu中执行:ip a |grep "global eth0",根据给出的IP(假设为172.21.120.38),先在win11里确认到这个IP的8000端口是通的,即在win11命令行中执行:telnet 172.21.120.38 8000是通的
- 在win11上找一个不用的tcp端口,这里选18000端口
- 以管理员权限运行powershell,执行:netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=18000 connectaddress=172.21.120.38 connectport=8000,然后执行:telnet localhost 18000,结果是通的就表明配置成功了。(注:这个转发配置重启后仍然是有效的,可以用命令:netsh interface portproxy show v4tov4来查看)
在dify的模型供应商配置中选择“OpenAI-API-compatible”,按如下配置:
模型类型:LLM
模型名称:QwQ-32B-light
API Key:token-abc123 (注:根据vllm运行参数中的--api-key进行配置)
API endpoint URL:http://host.docker.internal:18000/v1
2
3
4
对于docker的dify版本升级,建议升级前把自己创建的应用先导出备份,以免因操作不当(比如使用了docker compse rm),导致升级后之前创建的应用都不见了😭
# vllm启停脚本
为了便于vllm启动,不需要每次先切虚拟环境再输入启动命令,对虚拟环境的activate文件进行优化
cd ~/pythonvenv/bin
cp activate activate-qwq-32b-light-start
vi activate-qwq-32b-light-start
2
3
4
5
如果需要看vllm启动后打印信息的,在activate-qwq-32b-light-start文件最后追加
python3 -m vllm.entrypoints.openai.api_server --model /mnt/e/model/QwQ-32B-light/QwQ-32B-light.gguf --tokenizer /mnt/e/model/QwQ-32B-light --served-model-name QwQ-32B-light --dtype=half --api-key token-abc123 --max_model_len 4096 --gpu_memory_utilization 0.98 --trust-remote-code --enforce_eager
如果不需要看vllm启动后打印信息的,则可以使用nohup方式
nohup python3 -m vllm.entrypoints.openai.api_server --model /mnt/e/model/QwQ-32B-light/QwQ-32B-light.gguf --tokenizer /mnt/e/model/QwQ-32B-light --served-model-name QwQ-32B-light --dtype=half --api-key token-abc123 --max_model_len 4096 --gpu_memory_utilization 0.98 --trust-remote-code --enforce_eager >/dev/null 2>&1 &
在~/sbin目录下放置启停脚本
启动脚本:qwq-32b-light_start.sh
#!/bin/bash
cd ~/pythonvenv/bin
source activate-qwq-32b-light-start
2
3
如果在activate-qwq-32b-light-start是以nohup方式启动的vllm,则可以配置停止脚本:qwq-32b-light_stop.sh
#!/bin/bash
kill -9 $(ps -ef|grep 'python3 -c from multiprocessing.spawn import spawn_main'|grep ' --multiprocessing-fork' |grep -v grep|awk '{print $2}')
2
如果在activate-qwq-32b-light-start是以nohup方式启动的vllm,且把vllm作为服务使用的,则可以配置检活脚本:qwq-32b-light_check.sh
#!/bin/bash
prcoess_id=$(ps -ef|grep 'python3 -c from multiprocessing.spawn import spawn_main'|grep ' --multiprocessing-fork' |grep -v grep|awk '{print $2}')
if [ -z ${prcoess_id} ]; then
/bin/bash ~/sbin/qwq-32b-light_start.sh
fi
2
3
4
5
再附赠一个小提示:如果不给ubuntu下的脚本赋执行权限,那要使用bash+脚本名,而不是像centos或openEuler那样使用sh+脚本名
🌻🌻🌻