# 自定义 vLLM 容器 这是一个基于 Fedora 的 Docker/Podman 容器,专为在 AMD Radeon R9700 (gfx1201) GPU 上运行 vLLM 而设计。 ## 特性 - 基于 Fedora 43 - 使用最新的 TheRock ROCm 7.x SDK - 包含 PyTorch 预发布版本(ROCm 支持) - 内置 Flash-Attention(ROCm 版本) - 支持多种大型语言模型 - 基于配置文件的启动方式 - 仅支持本地模型(无网络下载功能) - 多模型配置支持 - **提供标准的 OpenAI API 服务** - **智能部署(自动检测 Git 更新)** ## 快速开始 ### 1. 构建并运行(推荐) ```bash # 赋予脚本执行权限 chmod +x build_and_run.sh # 一键构建并运行 ./build_and_run.sh ``` ### 2. 手动构建和运行 ```bash # 构建镜像 docker build -t custom-vllm-r9700:latest . # 运行容器 docker run -it --device /dev/dri --device /dev/kfd \ --group-add video --group-add render --security-opt seccomp=unconfined \ -v /opt/models:/models \ -v /opt/model_config.yaml:/etc/vllm/model_config.yaml \ -e LOCAL_MODEL_DIR=/models \ custom-vllm-r9700:latest ``` ## 构建容器 在项目目录中运行: ```bash docker build -t custom-vllm-r9700:latest . ``` ## 使用方法 ### 使用 Docker/Podman ```bash docker run -it --device /dev/dri --device /dev/kfd \ --group-add video --group-add render --security-opt seccomp=unconfined \ -v /opt/models:/models \ -v /opt/model_config.yaml:/etc/vllm/model_config.yaml \ -e LOCAL_MODEL_DIR=/models \ custom-vllm-r9700:latest ``` ### 使用 Toolbx(Fedora) ```bash toolbox create vllm-custom \ --image custom-vllm-r9700:latest \ -- --device /dev/dri --device /dev/kfd \ --group-add video --group-add render --security-opt seccomp=unconfined toolbox enter vllm-custom ``` ### 使用 Distrobox(Ubuntu) ```bash distrobox create -n vllm-custom \ --image custom-vllm-r9700:latest \ --additional-flags "--device /dev/kfd --device /dev/dri --group-add video --group-add render --security-opt seccomp=unconfined" distrobox enter vllm-custom ``` ## 配置文件 容器使用 YAML 格式的配置文件来设置 vLLM 服务器参数。配置文件需要挂载到 `/etc/vllm/model_config.yaml`。项目根目录中提供了配置文件示例 `model_config.yaml.example`,您可以参考它来创建自己的配置文件。 ### 配置文件示例 ```yaml # model_config.yaml - 多模型配置示例 # 默认启动的模型 default: "deepseek_r1_distill_qwen_32b_awq" # 模型配置 models: deepseek_r1_distill_qwen_14b: path: "/models/DeepSeek-R1-Distill-Qwen-14B" name: "DeepSeek-R1-Distill-Qwen-14B" max_model_len: 8192 gpu_memory_utilization: 0.9 port: 2001 dtype: "float16" quantization: "awq" tensor_parallel_size: 1 enforce_eager: true api_key: "sk-14b-20240101-abcdef123456" deepseek_r1_distill_qwen_32b_awq: path: "/models/DeepSeek-R1-Distill-Qwen-32B-AWQ" name: "DeepSeek-R1-Distill-Qwen-32B-AWQ" # 模型性能参数 max_model_len: 32768 gpu_memory_utilization: 0.95 enforce_eager: true max_num_seqs: 2 max_num_batched_tokens: 1024 block_size: 16 tensor_parallel_size: 1 swap_space: 0 # 新增:采样参数默认值 sampling_defaults: temperature: 0.6 max_tokens: 4096 top_p: 0.9 frequency_penalty: 0.0 presence_penalty: 0.0 stop: - "用户:" - "助手:" - "###" - "问题:" - "回答:" # 其他配置 dtype: "auto" quantization: "awq" port: 2001 api_key: "sk-32b-20240101-ghijk789012" glm_4_7_flash_awq: path: "/models/GLM-4.7-Flash-AWQ" name: "GLM-4.7-Flash-AWQ" # 模型性能参数 max_model_len: 32768 gpu_memory_utilization: 0.9 enforce_eager: false max_num_seqs: 2 max_num_batched_tokens: 1024 block_size: 16 tensor_parallel_size: 1 swap_space: 0 # 新增:采样参数默认值 sampling_defaults: temperature: 0.6 max_tokens: 4096 top_p: 0.9 frequency_penalty: 0.0 presence_penalty: 0.0 stop: - "用户:" - "助手:" - "###" - "问题:" - "回答:" # 其他配置 dtype: "auto" quantization: "awq" port: 2001 api_key: "sk-32b-20240101-ghijk789012" qwen3_vl_32b_instruct_awq: path: "/models/Qwen3-VL-32B-Instruct-AWQ" name: "Qwen3-VL-32B-Instruct-AWQ" max_model_len: 32768 gpu_memory_utilization: 0.7 port: 2001 dtype: "auto" quantization: "awq" tensor_parallel_size: 1 enforce_eager: true api_key: "sk-glm-20240101-lmnop345678" # 服务器通用设置 server: host: "0.0.0.0" log_level: "info" # 全局管理员密钥(拥有所有模型的访问权限) admin_key: "sk-admin-20240101-xyz789" # 允许的请求头名称(支持多个,按顺序检查) api_key_headers: ["Authorization", "X-API-Key", "api-key"] # 是否允许通过查询参数传递密钥 allow_query_param: true # 查询参数名称 api_key_param: "api_key" ``` ### 配置参数说明 - `default`:默认启动的模型名称 - `models`:模型配置列表 - 每个模型包含: - `path`:模型路径(相对于 LOCAL_MODEL_DIR) - `name`:模型名称 - `max_model_len`:最大模型上下文长度 - `gpu_memory_utilization`:GPU 内存利用率 - `port`:服务器端口 - `dtype`:数据类型 - `quantization`:量化方式 - `tensor_parallel_size`:张量并行度 - `enforce_eager`:是否强制使用 eager 模式 - `max_num_seqs`:最大并发请求数 - `max_num_batched_tokens`:最大批量 tokens 数 - `block_size`:块大小 - `swap_space`:交换空间大小 - `sampling_defaults`:采样参数默认值 - `api_key`:API 密钥(用于 OpenAI 兼容模式) - `server`:服务器通用设置 - `host`:服务器主机地址 - `log_level`:日志级别 - `admin_key`:全局管理员密钥 - `api_key_headers`:允许的请求头名称 - `allow_query_param`:是否允许通过查询参数传递密钥 - `api_key_param`:查询参数名称 ## 环境变量 - `LOCAL_MODEL_DIR`:本地模型目录路径(必须设置,默认:/models) - `VLLM_CONFIG_FILE`:配置文件路径(默认:/etc/vllm/model_config.yaml) ## 启动 vLLM 服务器 ### 使用智能部署脚本(推荐) 项目提供了 `build_and_run.sh` 脚本,具有智能检测和自动部署功能: **智能部署逻辑:** 1. **检测 Git 代码更新**: - 自动拉取远程仓库最新代码 - 比较本地和远程代码版本 - 检测本地未提交的更改 2. **智能构建决策**: - ✅ 代码有更新 → 重新构建镜像 - ✅ 本地有更改 → 重新构建镜像 - ✅ 镜像不存在 → 构建镜像 - ⏭️ 代码无更新且镜像存在 → 跳过构建,直接部署 3. **自动部署**: - 停止并删除旧容器 - 使用新镜像(或现有镜像)启动新容器 ```bash # 赋予执行权限 chmod +x build_and_run.sh # 智能部署(自动检测 Git 更新) ./build_and_run.sh # 强制重新构建(忽略 Git 状态) ./build_and_run.sh -f # 仅停止并删除容器 ./build_and_run.sh -s # 指定端口运行 ./build_and_run.sh -p 8080 # 指定配置文件和模型目录 ./build_and_run.sh -c /opt/model_config.yaml -m /opt/models # 交互式运行(前台运行) ./build_and_run.sh -i # 指定 Git 分支 ./build_and_run.sh -b master ``` **脚本选项:** - `-f, --force`:强制重新构建镜像(忽略 Git 状态) - `-s, --stop`:仅停止并删除容器 - `-d, --detach`:后台运行容器(默认) - `-i, --interactive`:交互式运行容器 - `-c, --config FILE`:指定配置文件路径 - `-m, --models DIR`:指定模型目录路径 - `-p, --port PORT`:指定服务端口 - `-b, --branch NAME`:指定 Git 分支(默认:main) - `-h, --help`:显示帮助信息 **使用场景:** - **首次部署**:直接运行 `./build_and_run.sh`,自动构建并部署 - **日常更新**:运行 `./build_and_run.sh`,自动检测代码更新并重新部署 - **快速重启**:代码无更新时,跳过构建,直接重启容器 - **强制更新**:使用 `-f` 参数强制重新构建 ### 手动部署 ```bash # 1. 构建镜像 docker build -t custom-vllm-r9700:latest . # 2. 运行容器 docker run -it --device /dev/dri --device /dev/kfd \ --group-add video --group-add render --security-opt seccomp=unconfined \ -v /opt/models:/models \ -v /opt/model_config.yaml:/etc/vllm/model_config.yaml \ -e LOCAL_MODEL_DIR=/models \ custom-vllm-r9700:latest ``` ### 容器内运行 进入容器后,可以使用以下命令启动 vLLM 服务器: ```bash # 使用默认模型启动 start-vllm # 或指定模型名称启动 start-vllm deepseek_r1_distill_qwen_14b # 或直接指定模型路径 vllm serve /models/model-name --tensor-parallel-size 2 --max-model-len 128000 ``` ## 测试 API(OpenAI 兼容) vLLM 提供与 OpenAI API 完全兼容的服务接口。 ### 1. 使用 curl 测试 ```bash # 聊天补全接口 curl -X POST http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-32b-20240101-ghijk789012" \ -d '{ "model": "deepseek_r1_distill_qwen_32b_awq", "messages": [ {"role": "user", "content": "你好,请介绍一下你自己"} ], "temperature": 0.6, "max_tokens": 4096, "top_p": 0.9 }' # 文本补全接口 curl -X POST http://localhost:8000/v1/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-32b-20240101-ghijk789012" \ -d '{ "model": "deepseek_r1_distill_qwen_32b_awq", "prompt": "Once upon a time", "max_tokens": 100 }' # 列出可用模型 curl http://localhost:8000/v1/models \ -H "Authorization: Bearer sk-32b-20240101-ghijk789012" ``` ### 2. 使用 Python OpenAI SDK ```python from openai import OpenAI # 初始化客户端 client = OpenAI( base_url="http://localhost:8000/v1", api_key="sk-32b-20240101-ghijk789012" ) # 聊天补全 response = client.chat.completions.create( model="deepseek_r1_distill_qwen_32b_awq", messages=[ {"role": "user", "content": "你好,请介绍一下你自己"} ], temperature=0.6, max_tokens=4096 ) print(response.choices[0].message.content) # 文本补全 response = client.completions.create( model="deepseek_r1_distill_qwen_32b_awq", prompt="Once upon a time", max_tokens=100 ) print(response.choices[0].text) ``` ### 3. 使用其他 OpenAI 兼容工具 由于提供标准的 OpenAI API,您可以使用任何支持 OpenAI 的工具和库,例如: - LangChain - LlamaIndex - AutoGen - FastChat - 等等 只需将 `base_url` 设置为 `http://localhost:8000/v1`,并使用配置的 API 密钥即可。 ## 本地模型目录结构 确保本地模型目录包含以下文件之一: - `config.json` - `pytorch_model.bin` - `model.safetensors` 正确的目录结构示例: ``` /opt/models/ ├── deepseek_r1_distill_qwen_14b/ │ ├── config.json │ └── model.safetensors ├── deepseek_r1_distill_qwen_32b_awq/ │ ├── config.json │ └── pytorch_model.bin ├── glm_4_7_flash_awq/ │ ├── config.json │ └── model.safetensors └── qwen3_vl_32b_instruct_awq/ ├── config.json └── pytorch_model.bin ``` ## 注意事项 - 确保您的 AMD Radeon R9700 GPU 驱动已正确安装 - 容器需要访问 GPU 设备,因此运行时需要添加 `--device /dev/dri --device /dev/kfd` 参数 - 首次启动时,vLLM 会编译计算图,可能需要较长时间 - 如果遇到内存不足的问题,可以调整 `gpu_memory_utilization` 参数 - API 密钥在配置文件的每个模型中单独配置,用于 OpenAI 兼容模式的认证 ## OpenAI API 兼容性 本容器提供的服务完全兼容 OpenAI API 标准,包括: - **聊天补全**:`/v1/chat/completions` - **文本补全**:`/v1/completions` - **模型列表**:`/v1/models` - **嵌入**:`/v1/embeddings`(如支持) 所有端点都支持标准的 OpenAI 请求格式和参数,您可以无缝切换使用。 ## 项目文件说明 - `Dockerfile` - Docker 镜像构建文件 - `README.md` - 项目说明文档 - `model_config.yaml.example` - 配置文件示例(包含所有模型配置参数) - `build_and_run.sh` - 智能部署脚本(自动检测 Git 更新) - `scripts/` - 脚本目录 - `start_vllm.py` - vLLM 启动脚本 - `01-rocm-envs.sh` - ROCm 环境配置 - `99-toolbox-banner.sh` - Toolbox 横幅 - `zz-venv-last.sh` - 虚拟环境配置 ## 部署说明 ### Docker 运行命令 ```bash docker run -it --device /dev/dri --device /dev/kfd \ --group-add video --group-add render --security-opt seccomp=unconfined \ -v /opt/models:/models \ -v /opt/model_config.yaml:/etc/vllm/model_config.yaml \ -e LOCAL_MODEL_DIR=/models \ custom-vllm-r9700:latest ``` **挂载说明:** - `/opt/models` - 本地模型目录,挂载到容器的 `/models` - `/opt/model_config.yaml` - 本地配置文件,挂载到容器的 `/etc/vllm/model_config.yaml` - `LOCAL_MODEL_DIR=/models` - 指定模型目录环境变量