#!/usr/bin/env python3 """vllm 平台检测补丁 问题 1:amdsmi 不可用时 platform 回退到 torch.version.hip 问题 2:rocm.py 中 logger.warning_once() 导致循环导入(默认不再改写;仅保留为显式开关) """ import os import re import sys import sysconfig import traceback VLLM_DIR = '/opt/vllm/vllm' VLLM_SRC_DIR = '/opt/vllm' def patch6_init_platform_fallback(): """补丁 6:platforms/__init__.py —— torch.version.hip 兜底""" f = os.path.join(VLLM_DIR, 'platforms', '__init__.py') c = open(f).read() old = " return 'vllm.platforms.rocm.RocmPlatform' if is_rocm else None" new = (" # amdsmi fallback: also check torch.version.hip\n" " if not is_rocm:\n" " try:\n" " import torch\n" " if torch.version.hip is not None:\n" " is_rocm = True\n" " except Exception:\n" " pass\n" " return 'vllm.platforms.rocm.RocmPlatform' if is_rocm else None") c2 = c.replace(old, new) if c2 != c: open(f, 'w').write(c2) print('Patch 6: __init__.py platform fallback applied.') else: print('Patch 6: already applied or pattern not found.') def patch7_rocm_break_import_cycle(): """补丁 7:platforms/rocm.py —— logger.warning_once → sys.stderr.write 默认启用安全的“整段 except 块”替换,避免 logger.warning_once() 在平台检测 期间触发循环导入,导致 current_platform 落到 UnspecifiedPlatform。 如需禁用,设置 VLLM_PATCH_ROCM_WARNING_ONCE=0。 """ if os.environ.get('VLLM_PATCH_ROCM_WARNING_ONCE') == '0': print('Patch 7: skipped (VLLM_PATCH_ROCM_WARNING_ONCE=0).') return f = os.path.join(VLLM_DIR, 'platforms', 'rocm.py') c = open(f).read() if 'amdsmi unavailable, using torch.cuda fallback' in c: print('Patch 7: already applied.') return pattern = re.compile( r'(\n\s*except Exception as e:\n' r'\s*logger\.debug\("Failed to get GCN arch via amdsmi: %s", e\)\n' r'\s*logger\.warning_once\(\n' r'(?:\s*"[^"]*"\n)+' r'\s*\)\n)', re.MULTILINE, ) def repl(match): indent = re.search(r'\n(\s*)except Exception as e:', match.group(1)).group(1) body_indent = indent + ' ' return ( f'\n{indent}except Exception as e:\n' f'{body_indent}import sys as _sys\n' f'{body_indent}_sys.stderr.write(' '"vLLM ROCm: amdsmi unavailable, using torch.cuda fallback for GPU detection\\n")\n' ) c2, n = pattern.subn(repl, c, count=1) if c2 != c: open(f, 'w').write(c2) print('Patch 7: rocm.py logger.warning_once circular import patch applied.') else: print('Patch 7: already applied or pattern not found.') def ensure_vllm_dist_info(): """为 /opt/vllm 源码导入创建最小 dist-info。 vLLM 平台检测会通过 importlib.metadata 查询 vllm 分发元数据/entry points。 如果只靠 PYTHONPATH 导入源码,没有 dist-info,就会出现: "The vLLM package was not found...",并可能得到 UnspecifiedPlatform。 """ try: import vllm except Exception: return version = getattr(vllm, '__version__', '0.1.dev1') or '0.1.dev1' site_packages = sysconfig.get_paths().get('purelib') if not site_packages: return dist_info = os.path.join(site_packages, f'vllm-{version}.dist-info') os.makedirs(dist_info, exist_ok=True) metadata = os.path.join(dist_info, 'METADATA') if not os.path.exists(metadata): with open(metadata, 'w') as fp: fp.write( 'Metadata-Version: 2.1\n' 'Name: vllm\n' f'Version: {version}\n' 'Summary: vLLM source tree mounted at /opt/vllm\n' ) with open(os.path.join(dist_info, 'top_level.txt'), 'w') as fp: fp.write('vllm\n') with open(os.path.join(dist_info, 'INSTALLER'), 'w') as fp: fp.write('mineru-rocm-runtime\n') with open(os.path.join(dist_info, 'entry_points.txt'), 'w') as fp: fp.write( '[vllm.platform_plugins]\n' 'rocm = vllm.platforms.rocm:rocm_platform_plugin\n' ) with open(os.path.join(dist_info, 'RECORD'), 'w') as fp: fp.write('') print(f'vllm dist-info ensured: {dist_info}') def ensure_vllm_installed(): """确保 vLLM Python 包在当前虚拟环境中可导入。 某些 MinerU 依赖安装流程后,site-packages 中可能缺少 vLLM 分发元数据,但 /opt/vllm 源码仍在。此时直接把 /opt/vllm 加入 PYTHONPATH/sys.path 再导入, 避免 editable 安装触发 pyproject 元数据校验失败。 """ try: import vllm # noqa: F401 return except ModuleNotFoundError as exc: if exc.name != 'vllm': raise if not os.path.isdir(VLLM_SRC_DIR): raise ModuleNotFoundError( 'vllm is not installed and /opt/vllm source directory is missing' ) print('vllm package missing; trying PYTHONPATH fallback with /opt/vllm...') current = os.environ.get('PYTHONPATH', '') paths = [p for p in current.split(':') if p] if VLLM_SRC_DIR not in paths: os.environ['PYTHONPATH'] = f"{VLLM_SRC_DIR}:{current}" if current else VLLM_SRC_DIR if VLLM_SRC_DIR not in sys.path: sys.path.insert(0, VLLM_SRC_DIR) import vllm # noqa: F401 print('vllm import recovered via PYTHONPATH fallback.') def main(): patch6_init_platform_fallback() patch7_rocm_break_import_cycle() try: ensure_vllm_installed() ensure_vllm_dist_info() import vllm from vllm.platforms import current_platform print(f'vllm runtime import OK: {vllm.__version__}, platform={type(current_platform).__name__}') if type(current_platform).__name__ == 'UnspecifiedPlatform': raise RuntimeError( 'vLLM platform detection returned UnspecifiedPlatform; ' 'ROCm backend is not usable. Check amdsmi, /dev/kfd, /dev/dri, ' 'and vllm.platform_plugins metadata.' ) except Exception: print('ERROR: vllm runtime import failed after platform patches:') traceback.print_exc() raise print('vllm platform patches done.') if __name__ == '__main__': main()