From 5c537988f5cbf2594cc8907fb23987def4cb0d77 Mon Sep 17 00:00:00 2001 From: i-peixingyu Date: Tue, 21 Jul 2026 16:47:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..30a046e --- /dev/null +++ b/README.md @@ -0,0 +1,148 @@ +# NV A100 vLLM Patched v2.0 + +基于 `harbor.4pd.io/dooke/vllm/vllm/vllm-openai:v0.11.0` 构建的 NVidia A100 GPU 专用 vLLM Docker 镜像,包含 4 类兼容性补丁。 + +## 基础镜像 + +- **镜像**: `harbor.4pd.io/dooke/vllm/vllm/vllm-openai:v0.11.0` +- **Python**: 3.12 +- **vLLM**: 0.11.0 + +## 补丁概览 + +此镜像在构建时打了 4 类补丁,启动时再执行运行时修复: + +| # | 文件 | 类型 | 说明 | +|---|------|------|------| +| 1 | `patch.py` | 构建时 | transformers `tokenization_utils_base.py` 库级补丁 | +| 2 | `patch_triton.py` | 构建时 | Triton Attention backend `validate_head_size` 绕过 | +| 3 | `detect_tokenizer.py` + `fix_tokenizer.py` | 运行时 | 自动检测并修复 tokenizer 配置 | +| 4 | `detect_head_size.py` | 运行时 | head_size 检测,自动切换 attention backend | + +--- + +## 修复 1: transformers 库级补丁 (`patch.py`) + +**问题**: 部分模型的 `tokenizer_config.json` 中 `extra_special_tokens` 字段是 list 而非 dict,导致 `transformers` 加载 tokenizer 时崩溃。 + +**修复位置**: `/usr/local/lib/python3.12/dist-packages/transformers/tokenization_utils_base.py` + +**逻辑**: 在 `SPECIAL_TOKENS_ATTRIBUTES` 赋值前插入类型检查——若 `special_tokens` 是 list,则转为 `{t: t}` 的 dict 形式: + +```python +# PATCH: some models have extra_special_tokens as list instead of dict +if isinstance(special_tokens, list): + special_tokens = {t: t for t in special_tokens} +``` + +--- + +## 修复 2: Triton Attention head_size 验证绕过 (`patch_triton.py`) + +**问题**: Triton Attention backend 的 `validate_head_size` 方法强制要求 `head_size >= 32`,某些非标准模型的 head_size 不满足此约束会直接报错。 + +**修复位置**: `/usr/local/lib/python3.12/dist-packages/vllm/v1/attention/backends/triton_attn.py` + +**逻辑**: 将整个 `validate_head_size` 方法体替换为直接 `return`,完全绕过验证。Triton 本身在运行时编译,实际支持任意 head_size。 + +--- + +## 修复 3: 运行时 tokenizer 配置修复 + +### `detect_tokenizer.py` — 检测器 + +根据模型目录中的文件自动判断 tokenizer 类型: + +| 特征文件 | 判定类型 | +|----------|----------| +| `tokenizer.json` | `fast` | +| `tokenizer.model` | `sentencepiece` | +| `vocab.json` + `merges.txt` | `bpe` | +| 以上均无 | `unknown` | + +同时读取 `tokenizer_config.json` 中的 `tokenizer_class` 字段作为原始类名。 + +### `fix_tokenizer.py` — 修复器 + +**运行时机**: 容器启动时(entrypoint 第一步) + +**逻辑**: +1. 将模型目录中的 tokenizer 相关文件拷贝到 `/tmp/fixed_tokenizer/` +2. 调用 `detect_tokenizer` 判断 tokenizer 类型 +3. 检查原 `tokenizer_class` 是否有效: + - 有效类:`transformers` 库中所有包含 "Tokenizer" 的类 + - 无效类(黑名单):`TokenizersBackend`、`TiktokenTokenizer` + - 缺失或无效时,按类型回退: + +| tokenizer 类型 | fallback 类 | +|----------------|-------------| +| `fast` | `PreTrainedTokenizerFast` | +| `sentencepiece` | `LlamaTokenizer` | +| `bpe` | `GPT2TokenizerFast` | +| `unknown` | `PreTrainedTokenizerFast` | + +4. 将修复后的配置写回 `/tmp/fixed_tokenizer/tokenizer_config.json` + +**环境变量**: +- `MODEL_DIR`:模型目录,默认 `/model` +- `FIX_TOKENIZER_DIR`:修复后 tokenizer 输出目录,默认 `/tmp/fixed_tokenizer` + +--- + +## 修复 4: head_size 检测 (`detect_head_size.py`) + +**运行时机**: 容器启动时(entrypoint 第二步) + +**逻辑**: +1. 读取 `${MODEL_DIR}/config.json` +2. 获取 `head_dim`;若无此字段,则用 `hidden_size / num_attention_heads` 计算 +3. 检查是否在 FlashAttention 支持的 head_size 白名单内: + +``` +{32, 64, 96, 128, 160, 192, 224, 256} +``` + +4. **退出码**: + - `0` — head_size 在白名单内,无需处理 + - `2` — head_size 不在白名单,将数值输出到 stdout,entrypoint 会据此切换 backend + +**entrypoint 联动**: 当 `detect_head_size.py` 返回退出码 2 时,entrypoint 自动设置 `VLLM_USE_FLASH_ATTN_PA=0`,切换到 Triton Attention backend。 + +--- + +## 入口脚本 (`entrypoint.sh`) + +启动流程: + +``` +1. python3 /opt/fix_tokenizer.py → 修复 tokenizer 配置 +2. python3 /opt/detect_head_size.py → 检测 head_size 兼容性 +3. 若非白名单 head_size → export VLLM_USE_FLASH_ATTN_PA=0(切到 Triton) +4. exec vllm serve ${MODEL_DIR} --tokenizer ${FIX_TOKENIZER_DIR} $@ +``` + +启动时自动以修复后的 tokenizer 目录运行 vLLM,用户只需挂载模型到 `/model`。 + +--- + +## 构建 + +```bash +docker build -t nv-vllm-patched:v2.0 . +``` + +--- + +## 与 K100 v2.0 的关系 + +此版本是 K100 vLLM Patched v2.0 的 NV A100 移植版。与 K100 版本的主要区别: + +- 基础镜像相同(`vllm-openai:v0.11.0`) +- K100 版本面向 K100 芯片集群(含 K100 专属 patch),NV A100 版本去掉了 K100 专属补丁 +- tokenizer 修复和 head_size 检测逻辑保持兼容 + +## 参考 + +- 上游 K100 版本:`k100-vllm-patched-v2.0/K100-vLLM-Patched-v2.0/` +- 第四范式 modelhub 平台:`modelhub.org.cn` +- vLLM 官方文档:https://docs.vllm.ai/